├── testTrack.cpg ├── testSegments.cpg ├── testTrack_pth.cpg ├── install.txt ├── mapmatcher ├── __init__.py ├── __init__.pyc ├── mapmatcher.pyc └── mapmatcher.py ├── example.PNG ├── mapMatch.PNG ├── testTrack.dbf ├── testTrack.sbn ├── testTrack.sbx ├── testTrack.shp ├── testTrack.shx ├── testSegments.dbf ├── testSegments.sbn ├── testSegments.sbx ├── testSegments.shp ├── testSegments.shx ├── testTrack_pth.dbf ├── testTrack_pth.sbn ├── testTrack_pth.sbx ├── testTrack_pth.shp ├── testTrack_pth.shx ├── dist └── mapmatcher-1.0.win32.exe ├── setup.py ├── testTrack.prj ├── testSegments.prj ├── testTrack_pth.prj ├── .gitattributes ├── .gitignore ├── LICENSE ├── mapMatch.pyt.xml ├── mapMatch.pyt ├── README.md ├── testSegments.shp.xml └── testTrack_pth.shp.xml /testTrack.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /testSegments.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /testTrack_pth.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /install.txt: -------------------------------------------------------------------------------- 1 | python setup.py bdist_wininst -------------------------------------------------------------------------------- /mapmatcher/__init__.py: -------------------------------------------------------------------------------- 1 | import mapmatcher 2 | -------------------------------------------------------------------------------- /example.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/example.PNG -------------------------------------------------------------------------------- /mapMatch.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/mapMatch.PNG -------------------------------------------------------------------------------- /testTrack.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack.dbf -------------------------------------------------------------------------------- /testTrack.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack.sbn -------------------------------------------------------------------------------- /testTrack.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack.sbx -------------------------------------------------------------------------------- /testTrack.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack.shp -------------------------------------------------------------------------------- /testTrack.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack.shx -------------------------------------------------------------------------------- /testSegments.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testSegments.dbf -------------------------------------------------------------------------------- /testSegments.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testSegments.sbn -------------------------------------------------------------------------------- /testSegments.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testSegments.sbx -------------------------------------------------------------------------------- /testSegments.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testSegments.shp -------------------------------------------------------------------------------- /testSegments.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testSegments.shx -------------------------------------------------------------------------------- /testTrack_pth.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack_pth.dbf -------------------------------------------------------------------------------- /testTrack_pth.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack_pth.sbn -------------------------------------------------------------------------------- /testTrack_pth.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack_pth.sbx -------------------------------------------------------------------------------- /testTrack_pth.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack_pth.shp -------------------------------------------------------------------------------- /testTrack_pth.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/testTrack_pth.shx -------------------------------------------------------------------------------- /mapmatcher/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/mapmatcher/__init__.pyc -------------------------------------------------------------------------------- /mapmatcher/mapmatcher.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/mapmatcher/mapmatcher.pyc -------------------------------------------------------------------------------- /dist/mapmatcher-1.0.win32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonscheider/mapmatching/HEAD/dist/mapmatcher-1.0.win32.exe -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | setup(name='mapmatcher', 3 | version='1.0', 4 | packages=['mapmatcher'], 5 | package_dir={'mapmatcher': 'mapmatcher'}, 6 | ) -------------------------------------------------------------------------------- /testTrack.prj: -------------------------------------------------------------------------------- 1 | PROJCS["RD_New",GEOGCS["GCS_Amersfoort",DATUM["D_Amersfoort",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Double_Stereographic"],PARAMETER["False_Easting",155000.0],PARAMETER["False_Northing",463000.0],PARAMETER["Central_Meridian",5.38763888888889],PARAMETER["Scale_Factor",0.9999079],PARAMETER["Latitude_Of_Origin",52.15616055555555],UNIT["Meter",1.0]] -------------------------------------------------------------------------------- /testSegments.prj: -------------------------------------------------------------------------------- 1 | PROJCS["RD_New",GEOGCS["GCS_Amersfoort",DATUM["D_Amersfoort",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Double_Stereographic"],PARAMETER["False_Easting",155000.0],PARAMETER["False_Northing",463000.0],PARAMETER["Central_Meridian",5.38763888888889],PARAMETER["Scale_Factor",0.9999079],PARAMETER["Latitude_Of_Origin",52.15616055555555],UNIT["Meter",1.0]] -------------------------------------------------------------------------------- /testTrack_pth.prj: -------------------------------------------------------------------------------- 1 | PROJCS["RD_New",GEOGCS["GCS_Amersfoort",DATUM["D_Amersfoort",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Double_Stereographic"],PARAMETER["False_Easting",155000.0],PARAMETER["False_Northing",463000.0],PARAMETER["Central_Meridian",5.38763888888889],PARAMETER["Scale_Factor",0.9999079],PARAMETER["Latitude_Of_Origin",52.15616055555555],UNIT["Meter",1.0]] -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 simonscheider 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mapMatch.pyt.xml: -------------------------------------------------------------------------------- 1 | 2 | 20170221130747001.0TRUE201703161906311500000005000ItemDescriptionc:\program files (x86)\arcgis\desktop10.3\Help\gpmapMatchA map matching tool based on a Hidden Markov ModelThis tool allows map matching (matching of track points to a network) in arcpy using a Hidden Markov model with probabilities parameterized based on spatial + network distances. 3 | It outputs a file "NameofInputTrack_pth.shp" inside the current workspace, which contains a path of network segments to which the track was mapped.Follows the ideas in Newson, Krumm (2009): "Hidden markov Map Matching through noise and sparseness" 4 | ArcToolbox Toolbox 5 | -------------------------------------------------------------------------------- /mapMatch.pyt: -------------------------------------------------------------------------------- 1 | 2 | import arcpy 3 | from mapmatcher import mapmatcher 4 | 5 | class Toolbox(object): 6 | def __init__(self): 7 | """Define the toolbox (the name of the toolbox is the name of the 8 | .pyt file).""" 9 | self.label = "mapMatch toolbox" 10 | self.alias = "mapMatcher" 11 | 12 | # List of tool classes associated with this toolbox 13 | self.tools = [mapMatch] 14 | 15 | 16 | class mapMatch(object): 17 | def __init__(self): 18 | """Define the tool (tool name is the name of the class).""" 19 | self.label = "mapMatch" 20 | self.description = "" 21 | '''This tool allows map matching (matching of track points to a network) 22 | in arcpy using a Hidden Markov model with 23 | probabilities parameterized based on spatial + network distances. 24 | Follows the ideas in Newson, Krumm (2009): 25 | "Hidden markov Map Matching through noise and sparseness" 26 | ''' 27 | self.canRunInBackground = False 28 | 29 | def getParameterInfo(self): 30 | #Define parameter definitions 31 | 32 | # Input Features parameter 33 | in_track = arcpy.Parameter( 34 | displayName="Input track (shp)", 35 | name="in_track", 36 | datatype="DEShapefile", 37 | parameterType="Required", 38 | direction="Input") 39 | 40 | #in_track.filter.type = 'FeatureClass' 41 | #in_track.filter.list = ["Point"] 42 | 43 | # Input Features parameter 44 | in_roads = arcpy.Parameter( 45 | displayName="Input road network (shp)", 46 | name="in_roads", 47 | datatype="DEShapefile", 48 | parameterType="Required", 49 | direction="Input") 50 | 51 | #in_roads.filter.type = 'FeatureClass' 52 | # in_roads.filter.list = ["Polyline"] 53 | 54 | # parameter 1 55 | decayconstantNet = arcpy.Parameter( 56 | displayName="Decay constant on network (in meter)", 57 | name="decayconstantNet", 58 | datatype="GPDouble", 59 | parameterType="Optional", 60 | direction="Input") 61 | 62 | decayconstantNet.value = "30" 63 | 64 | # parameter 2 65 | decayConstantEu = arcpy.Parameter( 66 | displayName="Decay constant for Eucl. distances (in meter)", 67 | name="decayconstantEu", 68 | datatype="GPDouble", 69 | parameterType="Optional", 70 | direction="Input") 71 | 72 | decayConstantEu.value = "10" 73 | 74 | # parameter 2 75 | maxDist = arcpy.Parameter( 76 | displayName="maximum Eucl. distance for selecting segment candidates (in meter)", 77 | name="maxDist", 78 | datatype="GPDouble", 79 | parameterType="Optional", 80 | direction="Input") 81 | 82 | maxDist.value = "50" 83 | 84 | ## # Derived Output Features parameter 85 | ## out_features = arcpy.Parameter( 86 | ## displayName="Output Features", 87 | ## name="out_features", 88 | ## datatype="GPFeatureLayer", 89 | ## parameterType="Derived", 90 | ## direction="Output") 91 | 92 | #out_features.parameterDependencies = [in_features.name] 93 | #out_features.schema.clone = True 94 | 95 | parameters = [in_track, in_roads, decayconstantNet, decayConstantEu, maxDist] 96 | 97 | return parameters 98 | 99 | def isLicensed(self): 100 | """Set whether tool is licensed to execute.""" 101 | return True 102 | 103 | def updateParameters(self, parameters): 104 | """Modify the values and properties of parameters before internal 105 | validation is performed. This method is called whenever a parameter 106 | has been changed.""" 107 | return 108 | 109 | def updateMessages(self, parameters): 110 | """Modify the messages created by internal validation for each tool 111 | parameter. This method is called after internal validation.""" 112 | return 113 | 114 | def execute(self, parameters, messages): 115 | """The source code of the tool.""" 116 | in_track = parameters[0].valueAsText 117 | in_roads = parameters[1].valueAsText 118 | decayconstantNet = parameters[2].valueAsText 119 | decayConstantEu = parameters[3].valueAsText 120 | maxDist = parameters[4].valueAsText 121 | 122 | opt = mapmatcher.mapMatch(in_track, in_roads, decayconstantNet, decayConstantEu,maxDist) 123 | mapmatcher.exportPath(opt, in_track) 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Map Matcher 2 | 3 | This python script allows map matching (matching of tracking points to a network) 4 | in arcpy using a Hidden Markov model with 5 | probabilities parameterized based on spatial + network distances. 6 | Follows the ideas in Newson, Krumm (2009): 7 | "Hidden markov Map Matching through noise and sparseness" 8 | 9 | Author: Simon Scheider 10 | 11 | Created: 16/03/2017 12 | 13 | 14 | ## Installation 15 | 16 | To install as a toolbox in ArcGIS, see [mapMaptch.pyt](#mapmatchpyt-arcgis-python-toolbox) 17 | 18 | The code is written in Python 2.7 and depends on: 19 | 20 | * arcpy (ships with ArcGIS and its own Python 2.7) 21 | * [networkx](https://networkx.github.io) 22 | 23 | `python pip install networkx` 24 | 25 | * note: requires installing GDAL first, which can be obtained as a windows wheel from [here](http://www.lfd.uci.edu/~gohlke/pythonlibs/) 26 | and then installed with pip locally: 27 | 28 | `python pip install GDAL-2.1.3-cp27-cp27m-win32.whl` 29 | 30 | To install the mapmatcher Python module, simply download and execute this windows executable: 31 | - [mapmatching/dist/mapmatcher-1.0.win32.exe](https://github.com/simonscheider/mapmatching/blob/master/dist/mapmatcher-1.0.win32.exe). 32 | 33 | ## Usage 34 | 35 | Example: 36 | 37 | `from mapmatcher import mapmatcher` 38 | 39 | `arcpy.env.workspace = 'C:/Users/simon/Documents/GitHub/mapmatching'` 40 | 41 | `opt = mapmatcher.mapMatch('testTrack.shp', 'testSegments.shp')` 42 | 43 | `#outputs testTrack_pth.shp` 44 | 45 | `mapmatcher.exportPath(opt, 'testTrack.shp')` 46 | 47 | The last method saves a new shape file named _testTrack_pth.shp_ in the current arcpy workspace, containing a sequence of segments to which the track was mapped. 48 | 49 | Results are shown here: 50 | 51 | 52 | 53 | 54 | The main method is _mapMatch_. Based on the Viterbi algorithm for Hidden Markov models, 55 | see https://en.wikipedia.org/wiki/Viterbi_algorithm, it gets trackpoints and segments, and returns the most probable segment path (a list of segments) for the list of points. 56 | 57 | ### Method _mapMatch_: 58 | * @param **track** = a shape file (filename) with point geometries representing a track, can be unprojected (WGS84). The order of points in this file should reflect the temporal order. 59 | 60 | * @param **segments** = a shape file of network segments, should be _projected_ (in meter) to compute Euclidean distances properly (e.g. GCS Amersfoord). _Note_: To compute network distances, the script turns this network into a graph using [networkx](https://networkx.github.io), based on coincidence of segment end points. It is therefore important that logically connected segments are also geometrically connected (no geometrical errors). Other than this, the script does have other requirements for the network. 61 | 62 | * @param _decayconstantNet_ (optional) = the network distance (in meter) after which the match probability falls under 0.34 ([exponential decay](https://en.wikipedia.org/wiki/Exponential_decay)). Default is 30 meters. This distance parameter depends on the intervals between successing points in the track. 63 | 64 | * @param _decayConstantEu_ (optional) = the Euclidean distance (in meter) after which the match probability falls under 0.34 (exponential decay). Default is 10 meters. This distance parameter depends on the measurement accuracy of tracking points. 65 | 66 | * @param _maxDist_ (optional) = the Euclidean distance threshold (in meter) for taking into account segments candidates. Default is 50 meters. Depends also on measurement accuracy of track points. 67 | 68 | * result = delivers back a path (a list of segment ids). 69 | 70 | #### Note: 71 | Depending on the type of movement, optional parameters need to be fine tuned to get optimal results. For example, when tracking frequency is very slow, then track points are far apart, and then _decayconstantNet_ needs to be increased accordingly. 72 | 73 | ### Method _exportPath_ : 74 | Exports the path into a shape file named _segments_pth.shp_ inside the current ArcGIS workspace. 75 | 76 | 77 | # mapMatch.pyt (ArcGIS Python toolbox) 78 | 79 | To use the Python method as an ArcGIS toolbox, you need to do the following: 80 | 81 | 1. In your ArcGIS Python version (e.g. Folder `C:\Python27\ArcGIS10.3\Lib\site-packages`), install required modules for GDAL and networkx in a cmd window: 82 | 83 | - if you have not installed it yet, install pip (http://pip.readthedocs.io/en/latest/installing/). 84 | - Download a suitable GDAL wheel from [here](http://www.lfd.uci.edu/~gohlke/pythonlibs/). Then execute: 85 | - `python pip install GDAL-2.1.3-cp27-cp27m-win32.whl` 86 | - `python pip install networkx` 87 | 88 | 2. Install mapmatcher Python module by downloading and executing the windows executable [mapmatching/dist/mapmatcher-1.0.win32.exe](https://github.com/simonscheider/mapmatching/blob/master/dist/mapmatcher-1.0.win32.exe). Make sure you select exactly the Python installation that ships with your ArcGIS as a target folder. 89 | 90 | 3. Download the ArcGIS Python toolbox [mapMatch.pyt](https://github.com/simonscheider/mapmatching/blob/master/mapMatch.pyt), together with meta data files [mapMatch.mapMatch.pyt.xml](https://github.com/simonscheider/mapmatching/blob/master/mapMatch.mapMatch.pyt.xml) and [mapMatch.pyt.xml](https://github.com/simonscheider/mapmatching/blob/master/mapMatch.pyt.xml) and drop it anywhere on your computer. 91 | 92 | 4. Now you can open the toolbox by clicking on it inside an ArcGIS Catalog Window: 93 | 94 | 95 | The tool saves a new shape file named _NameofInputTrack_pth.shp_ inside the current ArcGIS workspace that contains the path of segments to which the track was mapped. When executing, make sure the network is as small as possible to speed up. 96 | -------------------------------------------------------------------------------- /testSegments.shp.xml: -------------------------------------------------------------------------------- 1 | 2 | 20170207134751001.0FALSENLstreets002file://\\ad.geo.uu.nl\dfs\Plaza\mze\STreets2013.gdbLocal Area Network1561.077893290167.870354292906.746645612814.1809231ProjectedGCS_AmersfoortLinear Unit: Meter (1.000000)<ProjectedCoordinateSystem xsi:type='typens:ProjectedCoordinateSystem' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:typens='http://www.esri.com/schemas/ArcGIS/10.3'><WKT>PROJCS[&quot;RD_New&quot;,GEOGCS[&quot;GCS_Amersfoort&quot;,DATUM[&quot;D_Amersfoort&quot;,SPHEROID[&quot;Bessel_1841&quot;,6377397.155,299.1528128]],PRIMEM[&quot;Greenwich&quot;,0.0],UNIT[&quot;Degree&quot;,0.0174532925199433]],PROJECTION[&quot;Double_Stereographic&quot;],PARAMETER[&quot;False_Easting&quot;,155000.0],PARAMETER[&quot;False_Northing&quot;,463000.0],PARAMETER[&quot;Central_Meridian&quot;,5.38763888888889],PARAMETER[&quot;Scale_Factor&quot;,0.9999079],PARAMETER[&quot;Latitude_Of_Origin&quot;,52.15616055555555],UNIT[&quot;Meter&quot;,1.0],AUTHORITY[&quot;EPSG&quot;,28992]]</WKT><XOrigin>-30515500</XOrigin><YOrigin>-30279500</YOrigin><XYScale>146716411.36275291</XYScale><ZOrigin>-100000</ZOrigin><ZScale>10000</ZScale><MOrigin>-100000</MOrigin><MScale>10000</MScale><XYTolerance>0.001</XYTolerance><ZTolerance>0.001</ZTolerance><MTolerance>0.001</MTolerance><HighPrecision>true</HighPrecision><WKID>28992</WKID><LatestWKID>28992</LatestWKID></ProjectedCoordinateSystem>RD_New201507060906340020150706090847001500000005000ItemDescriptionMicrosoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; Esri ArcGIS 10.3.0.4322NLstreets13.0759777.42421553.50262250.606694Netherlands and surroundings with limited attribute table: Subset ESRI streetmap 2013 (Tde Jong)streets NetherlandsFile Geodatabase Feature ClassdatasetEPSG8.2.62072326SimpleFALSE2072326TRUEFALSENLstreetsFeature Class2072326OBJECTIDOBJECTIDOID400Internal feature number.EsriSequential unique whole numbers that are automatically generated.ShapeShapeGeometry000Feature geometry.EsriCoordinates defining the features.FOWFOWInteger400FREEWAYFREEWAYInteger400BACKRDBACKRDInteger400RDCONDRDCONDInteger400PRIVATERDPRIVATERDInteger400ONEWAYONEWAYString200KPHKPHInteger400COUNTRYCOUNTRYString4000ROAD_CLROAD_CLInteger400FULLNAMEFULLNAMEString10000RESTR_01RESTR_01String100RESTR_02RESTR_02String100RESTR_04RESTR_04String100RESTR_05RESTR_05String100RESTR_06RESTR_06String100RESTR_07RESTR_07String100RESTR_09RESTR_09String100RESTR_10RESTR_10String100NET_LEVELNET_LEVELInteger400Shape_LengthShape_LengthDouble800Length of feature in internal units.EsriPositive real numbers that are automatically generated.20150706/9j/4AAQSkZJRgABAQEAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a 3 | HBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy 4 | MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCACFAMgDASIA 5 | AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA 6 | AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3 7 | ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm 8 | p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA 9 | AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx 10 | BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK 11 | U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3 12 | uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iii 13 | gAooooAKKKKACiiigAooooAKKKqajqdlpNt9ovrhIY8hQTklj6ADkn2FNJt2QFuiuUkk17xHdo+m 14 | 30miWEHyzJNaq88zMqtjBP7vAIx3yTx0pfFN14cs7WC38V6gHilbfHAyn5nXuojG7jOOp6962VB8 15 | yje7fRav+vmK50ouYDP5AmjM2CfL3jdgdTjr3qsusWL6y+kpK7XscYldFichFOcEtjaM4PBOa+f9 16 | Z+Jtvp7yxeDrJrXTXkeRjJ83mkn5nCHgDPZ92cjhQMF+n/Eu+j0C7uDq0dv4hViqxJbKkJiwCGIH 17 | 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 95 | AooooAKKKKACiiigAooooA//2Q== 96 | -------------------------------------------------------------------------------- /testTrack_pth.shp.xml: -------------------------------------------------------------------------------- 1 | 2 | 20170207134751001.0FALSEtestTrack_pth002file://\\UU062133\C$\Users\schei008\Documents\Github\mapmatching\testTrack_pth.shpLocal Area Network1561.077893290167.870354292906.746645612814.18092310.000ProjectedGCS_AmersfoortLinear Unit: Meter (1.000000)<ProjectedCoordinateSystem xsi:type='typens:ProjectedCoordinateSystem' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:typens='http://www.esri.com/schemas/ArcGIS/10.3'><WKT>PROJCS[&quot;RD_New&quot;,GEOGCS[&quot;GCS_Amersfoort&quot;,DATUM[&quot;D_Amersfoort&quot;,SPHEROID[&quot;Bessel_1841&quot;,6377397.155,299.1528128]],PRIMEM[&quot;Greenwich&quot;,0.0],UNIT[&quot;Degree&quot;,0.0174532925199433]],PROJECTION[&quot;Double_Stereographic&quot;],PARAMETER[&quot;False_Easting&quot;,155000.0],PARAMETER[&quot;False_Northing&quot;,463000.0],PARAMETER[&quot;Central_Meridian&quot;,5.38763888888889],PARAMETER[&quot;Scale_Factor&quot;,0.9999079],PARAMETER[&quot;Latitude_Of_Origin&quot;,52.15616055555555],UNIT[&quot;Meter&quot;,1.0],AUTHORITY[&quot;EPSG&quot;,28992]]</WKT><XOrigin>-30515500</XOrigin><YOrigin>-30279500</YOrigin><XYScale>146716411.36275291</XYScale><ZOrigin>-100000</ZOrigin><ZScale>10000</ZScale><MOrigin>-100000</MOrigin><MScale>10000</MScale><XYTolerance>0.001</XYTolerance><ZTolerance>0.001</ZTolerance><MTolerance>0.001</MTolerance><HighPrecision>true</HighPrecision><WKID>28992</WKID><LatestWKID>28992</LatestWKID></ProjectedCoordinateSystem>RD_NewFeatureClassToFeatureClass segments_lyr C:\Users\schei008\Documents\Github\mapmatching testTrack_pth # "OBJECTID "OBJECTID" true true false 10 Long 0 10 ,First,#,segments_lyr,OBJECTID,-1,-1;FOW "FOW" true true false 10 Long 0 10 ,First,#,segments_lyr,FOW,-1,-1;FREEWAY "FREEWAY" true true false 10 Long 0 10 ,First,#,segments_lyr,FREEWAY,-1,-1;BACKRD "BACKRD" true true false 10 Long 0 10 ,First,#,segments_lyr,BACKRD,-1,-1;RDCOND "RDCOND" true true false 10 Long 0 10 ,First,#,segments_lyr,RDCOND,-1,-1;PRIVATERD "PRIVATERD" true true false 10 Long 0 10 ,First,#,segments_lyr,PRIVATERD,-1,-1;ONEWAY "ONEWAY" true true false 2 Text 0 0 ,First,#,segments_lyr,ONEWAY,-1,-1;KPH "KPH" true true false 10 Long 0 10 ,First,#,segments_lyr,KPH,-1,-1;COUNTRY "COUNTRY" true true false 40 Text 0 0 ,First,#,segments_lyr,COUNTRY,-1,-1;ROAD_CL "ROAD_CL" true true false 10 Long 0 10 ,First,#,segments_lyr,ROAD_CL,-1,-1;FULLNAME "FULLNAME" true true false 100 Text 0 0 ,First,#,segments_lyr,FULLNAME,-1,-1;RESTR_01 "RESTR_01" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_01,-1,-1;RESTR_02 "RESTR_02" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_02,-1,-1;RESTR_04 "RESTR_04" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_04,-1,-1;RESTR_05 "RESTR_05" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_05,-1,-1;RESTR_06 "RESTR_06" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_06,-1,-1;RESTR_07 "RESTR_07" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_07,-1,-1;RESTR_09 "RESTR_09" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_09,-1,-1;RESTR_10 "RESTR_10" true true false 1 Text 0 0 ,First,#,segments_lyr,RESTR_10,-1,-1;NET_LEVEL "NET_LEVEL" true true false 10 Long 0 10 ,First,#,segments_lyr,NET_LEVEL,-1,-1;Shape_Leng "Shape_Leng" true true false 19 Double 0 0 ,First,#,segments_lyr,Shape_Leng,-1,-1" #201802201508410020180220150841001500000005000ItemDescriptionMicrosoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; Esri ArcGIS 10.3.1.4959testTrack_pth13.0759777.42421553.50262250.606694Netherlands and surroundings with limited attribute table: Subset ESRI streetmap 2013 (Tde Jong)streets NetherlandsShapefile0.000datasetEPSG8.6.20SimpleFALSE0FALSEFALSEtestTrack_pthFeature Class0FIDFIDOID400Internal feature number.EsriSequential unique whole numbers that are automatically generated.OBJECTIDOBJECTIDInteger10100Internal feature number.EsriSequential unique whole numbers that are automatically generated.ShapeShapeGeometry000Feature geometry.EsriCoordinates defining the features.FOWFOWInteger10100FREEWAYFREEWAYInteger10100BACKRDBACKRDInteger10100RDCONDRDCONDInteger10100PRIVATERDPRIVATERDInteger10100ONEWAYONEWAYString200KPHKPHInteger10100COUNTRYCOUNTRYString4000ROAD_CLROAD_CLInteger10100FULLNAMEFULLNAMEString10000RESTR_01RESTR_01String100RESTR_02RESTR_02String100RESTR_04RESTR_04String100RESTR_05RESTR_05String100RESTR_06RESTR_06String100RESTR_07RESTR_07String100RESTR_09RESTR_09String100RESTR_10RESTR_10String100NET_LEVELNET_LEVELInteger10100Shape_LengShape_LengDouble190020180220/9j/4AAQSkZJRgABAQEAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a 3 | HBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy 4 | MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCACFAMgDASIA 5 | AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA 6 | AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3 7 | ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm 8 | p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA 9 | AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx 10 | BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK 11 | U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3 12 | uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iii 13 | gAooooAKKKKACiiigAooooAKKKqajqdlpNt9ovrhIY8hQTklj6ADkn2FNJt2QFuiuUkk17xHdo+m 14 | 30miWEHyzJNaq88zMqtjBP7vAIx3yTx0pfFN14cs7WC38V6gHilbfHAyn5nXuojG7jOOp6962VB8 15 | yje7fRav+vmK50ouYDP5AmjM2CfL3jdgdTjr3qsusWL6y+kpK7XscYldFichFOcEtjaM4PBOa+f9 16 | Z+Jtvp7yxeDrJrXTXkeRjJ83mkn5nCHgDPZ92cjhQMF+n/Eu+j0C7uDq0dv4hViqxJbKkJiwCGIH 17 | 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 95 | AooooAKKKKACiiigAooooA//2Q== 96 | -------------------------------------------------------------------------------- /mapmatcher/mapmatcher.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------------------------------------------------- 3 | # Name: mapMatcher 4 | # Purpose: This python script allows map matching (matching of track points to a network) 5 | # in arcpy using a Hidden Markov model with 6 | # probabilities parameterized based on spatial + network distances. 7 | # Follows the ideas in Newson, Krumm (2009): 8 | # "Hidden markov Map Matching through noise and sparseness" 9 | # 10 | # Example usage under '__main__' 11 | # 12 | # Author: Simon Scheider 13 | # 14 | # Created: 01/03/2017 15 | # Copyright: (c) simon 2017 16 | # Licence: 17 | 18 | The code is written in Python 2.7 and depends on: 19 | 20 | * arcpy (ships with ArcGIS and its own Python 2.7) 21 | * networkx (# python pip install networkx (https://networkx.github.io)) 22 | (note: requires installing GDAL first, which can be obtained as a wheel from 23 | http://www.lfd.uci.edu/~gohlke/pythonlibs/ and then installed with pip locally: 24 | python pip install GDAL-2.1.3-cp27-cp27m-win32.whl 25 | ) 26 | 27 | #------------------------------------------------------------------------------- 28 | """ 29 | 30 | __author__ = "Simon Scheider" 31 | __copyright__ = "" 32 | 33 | 34 | import sys 35 | 36 | try: 37 | from math import exp, sqrt 38 | import os 39 | import arcpy 40 | arcpy.env.overwriteOutput = True 41 | import networkx as nx 42 | import time 43 | 44 | except ImportError: 45 | print "Error: missing one of the libraries (arcpy, networkx)" 46 | sys.exit() 47 | 48 | 49 | 50 | def mapMatch(track, segments, decayconstantNet = 30, decayConstantEu = 10, maxDist = 50, addfullpath = True): 51 | """ 52 | The main method. Based on the Viterbi algorithm for Hidden Markov models, 53 | see https://en.wikipedia.org/wiki/Viterbi_algorithm. 54 | It gets trackpoints and segments, and returns the most probable segment path (a list of segments) for the list of points. 55 | Inputs: 56 | @param track = a shape file (filename) representing a track, can also be unprojected (WGS84) 57 | @param segments = a shape file of network segments, should be projected (in meter) to compute Euclidean distances properly (e.g. GCS Amersfoord) 58 | @param decayconstantNet (optional) = the network distance (in meter) after which the match probability falls under 0.34 (exponential decay). (note this is the inverse of lambda). 59 | This depends on the point frequency of the track (how far are track points separated?) 60 | @param decayConstantEu (optional) = the Euclidean distance (in meter) after which the match probability falls under 0.34 (exponential decay). (note this is the inverse of lambda). 61 | This depends on the positional error of the track points (how far can points deviate from their true position?) 62 | @param maxDist (optional) = the Euclidean distance threshold (in meter) for taking into account segments candidates. 63 | @param addfullpath (optional, True or False) = whether a contiguous full segment path should be outputted. If not, a 1-to-1 list of segments matching each track point is outputted. 64 | 65 | note: depending on the type of movement, optional parameters need to be fine tuned to get optimal results. 66 | """ 67 | #Make sure passed in parameters are floats 68 | decayconstantNet = float(decayconstantNet) 69 | decayConstantEu = float(decayConstantEu) 70 | maxDist= float(maxDist) 71 | 72 | #gest start time 73 | start_time = time.time() 74 | 75 | #this array stores, for each point in a track, probability distributions over segments, together with the (most probable) predecessor segment taking into account a network distance 76 | V = [{}] 77 | 78 | #get track points, build network graph (graph, endpoints, lengths) and get segment info from arcpy 79 | points = getTrackPoints(track, segments) 80 | r = getSegmentInfo(segments) 81 | endpoints = r[0] 82 | lengths = r[1] 83 | graph = getNetworkGraph(segments,lengths) 84 | pathnodes = [] #set of pathnodes to prevent loops 85 | 86 | #init first point 87 | sc = getSegmentCandidates(points[0], segments, decayConstantEu, maxDist) 88 | for s in sc: 89 | V[0][s] = {"prob": sc[s], "prev": None, "path": [], "pathnodes":[]} 90 | # Run Viterbi when t > 0 91 | for t in range(1, len(points)): 92 | V.append({}) 93 | #Store previous segment candidates 94 | lastsc = sc 95 | #Get segment candidates and their a-priori probabilities (based on Euclidean distance for current point t) 96 | sc = getSegmentCandidates(points[t], segments, decayConstantEu, maxDist) 97 | for s in sc: 98 | max_tr_prob = 0 99 | prev_ss = None 100 | path = [] 101 | for prev_s in lastsc: 102 | #determine the highest network transition probability from previous candidates to s and get the corresponding network path 103 | pathnodes = V[t-1][prev_s]["pathnodes"][-10:] 104 | n = getNetworkTransP(prev_s, s, graph, endpoints, lengths, pathnodes, decayconstantNet) 105 | np = n[0] #This is the network transition probability 106 | tr_prob = V[t-1][prev_s]["prob"]*np 107 | #this selects the most probable predecessor candidate and the path to it 108 | if tr_prob > max_tr_prob: 109 | max_tr_prob = tr_prob 110 | prev_ss = prev_s 111 | path = n[1] 112 | if n[2] != None: 113 | pathnodes.append(n[2]) 114 | #The final probability of a candidate is the product of a-priori and network transitional probability 115 | max_prob = sc[s] * max_tr_prob 116 | V[t][s] = {"prob": max_prob, "prev": prev_ss, "path": path, "pathnodes":pathnodes} 117 | 118 | #Now max standardize all p-values to prevent running out of digits 119 | maxv = max(value["prob"] for value in V[t].values()) 120 | maxv = (1 if maxv == 0 else maxv) 121 | for s in V[t].keys(): 122 | V[t][s]["prob"]=V[t][s]["prob"]/maxv 123 | 124 | 125 | intertime1 = time.time() 126 | print("--- Viterbi forward: %s seconds ---" % (intertime1 - start_time)) 127 | #print V 128 | 129 | #opt is the result: a list of (matched) segments [s1, s2, s3,...] in the exact order of the point track: [p1, p2, p3,...] 130 | opt = [] 131 | 132 | # get the highest probability at the end of the track 133 | max_prob = max(value["prob"] for value in V[-1].values()) 134 | previous = None 135 | if max_prob == 0: 136 | print " probabilities fall to zero (network distances in data are too large, try increasing network decay parameter)" 137 | 138 | # Get most probable ending state and its backtrack 139 | for st, data in V[-1].items(): 140 | if data["prob"] == max_prob: 141 | opt.append(st) 142 | previous = st 143 | break 144 | ## print " previous: "+str(previous) 145 | ## print " max_prob: "+str(max_prob) 146 | ## print " V -1: "+str(V[-1].items()) 147 | 148 | # Follow the backtrack till the first observation to fish out most probable states and corresponding paths 149 | for t in range(len(V) - 2, -1, -1): 150 | #Get the subpath between last and most probable previous segment and add it to the resulting path 151 | path = V[t + 1][previous]["path"] 152 | opt[0:0] =(path if path !=None else []) 153 | #Insert the previous segment 154 | opt.insert(0, V[t + 1][previous]["prev"]) 155 | previous = V[t + 1][previous]["prev"] 156 | intertime2 = time.time() 157 | print("--- Viterbi backtracking: %s seconds ---" % (intertime2 - intertime1)) 158 | 159 | #Clean the path (remove double segments and crossings) (only in full path option) 160 | print "path length before cleaning :" +str(len(opt)) 161 | opt = cleanPath(opt, endpoints) 162 | intertime3 = time.time() 163 | print("--- Path cleaning: %s seconds ---" % (intertime3 - intertime2)) 164 | print "final length: "+str(len(opt)) 165 | pointstr= [str(g.firstPoint.X)+' '+str(g.firstPoint.Y) for g in points] 166 | optstr= [str(i) for i in opt] 167 | print 'The path for points ['+' '.join(pointstr)+'] is: ' 168 | print '[' + ' '.join(optstr) + '] with highest probability of %s' % max_prob 169 | 170 | #If only a single segment candidate should be returned for each point: 171 | if addfullpath == False: 172 | opt = getpointMatches(points,opt) 173 | optstr= [str(i) for i in opt] 174 | print "Individual point matches: "+'[' + ' '.join(optstr) + ']' 175 | intertime4 = time.time() 176 | print("--- Picking point matches: %s seconds ---" % (intertime4 - intertime3)) 177 | 178 | return opt 179 | 180 | #Fishes out a 1-to-1 list of path segments nearest to the list of points in the track (not contiguous, may contain repeated segments) 181 | def getpointMatches(points, path): 182 | qr = '"OBJECTID" IN ' +str(tuple(path)) 183 | arcpy.SelectLayerByAttribute_management('segments_lyr',"NEW_SELECTION", qr) 184 | opta = [] 185 | for point in points: 186 | sdist = 100000 187 | candidate = '' 188 | cursor = arcpy.da.SearchCursor('segments_lyr', ["OBJECTID", "SHAPE@"]) 189 | for row in cursor: 190 | #compute the spatial distance 191 | dist = point.distanceTo(row[1]) 192 | if dist