SVN checkout 11/12/2010
[monav:monav.git] / plugins / contractionhierarchies / contractionhierarchies.cpp
1 /*
2 Copyright 2010  Christian Vetter veaac.fdirct@gmail.com
3
4 This file is part of MoNav.
5
6 MoNav is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 MoNav is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with MoNav.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "contractionhierarchies.h"
21 #include "compressedgraphbuilder.h"
22 #include "contractor.h"
23 #include "contractioncleanup.h"
24 #include "utils/qthelpers.h"
25
26 ContractionHierarchies::ContractionHierarchies()
27 {
28         m_settingsDialog = NULL;
29 }
30
31 ContractionHierarchies::~ContractionHierarchies()
32 {
33         if ( m_settingsDialog != NULL )
34                 delete m_settingsDialog;
35 }
36
37 QString ContractionHierarchies::GetName()
38 {
39         return "Contraction Hierarchies";
40 }
41
42 bool ContractionHierarchies:: LoadSettings( QSettings* settings )
43 {
44         if ( m_settingsDialog == NULL )
45                 m_settingsDialog = new CHSettingsDialog();
46         return m_settingsDialog->loadSettings( settings );
47 }
48
49 bool ContractionHierarchies::SaveSettings( QSettings* settings )
50 {
51         if ( m_settingsDialog == NULL )
52                 m_settingsDialog = new CHSettingsDialog();
53         return m_settingsDialog->saveSettings( settings );
54 }
55
56 int ContractionHierarchies::GetFileFormatVersion()
57 {
58         return 1;
59 }
60
61 ContractionHierarchies::Type ContractionHierarchies::GetType()
62 {
63         return Router;
64 }
65
66 QWidget* ContractionHierarchies::GetSettings()
67 {
68         if ( m_settingsDialog == NULL )
69                 m_settingsDialog = new CHSettingsDialog();
70         return m_settingsDialog;
71 }
72
73 bool ContractionHierarchies::Preprocess( IImporter* importer, QString dir )
74 {
75         if ( m_settingsDialog == NULL )
76                 m_settingsDialog = new CHSettingsDialog();
77         m_settingsDialog->getSettings( &m_settings );
78
79         QString filename = fileInDirectory( dir, "Contraction Hierarchies" );
80
81         std::vector< IImporter::RoutingNode > inputNodes;
82         std::vector< IImporter::RoutingEdge > inputEdges;
83
84         if ( !importer->GetRoutingNodes( &inputNodes ) )
85                 return false;
86         if ( !importer->GetRoutingEdges( &inputEdges ) )
87                 return false;
88
89         unsigned numEdges = inputEdges.size();
90         unsigned numNodes = inputNodes.size();
91
92         Contractor* contractor = new Contractor( numNodes, inputEdges );
93         std::vector< IImporter::RoutingEdge >().swap( inputEdges );
94         contractor->Run();
95
96         std::vector< Contractor::Witness > witnessList;
97         contractor->GetWitnessList( witnessList );
98
99         std::vector< ContractionCleanup::Edge > contractedEdges;
100         std::vector< ContractionCleanup::Edge > contractedLoops;
101         contractor->GetEdges( &contractedEdges );
102         contractor->GetLoops( &contractedLoops );
103         delete contractor;
104
105         ContractionCleanup* cleanup = new ContractionCleanup( inputNodes.size(), contractedEdges, contractedLoops, witnessList );
106         std::vector< ContractionCleanup::Edge >().swap( contractedEdges );
107         std::vector< ContractionCleanup::Edge >().swap( contractedLoops );
108         std::vector< Contractor::Witness >().swap( witnessList );
109         cleanup->Run();
110
111         std::vector< CompressedGraph::Edge > edges;
112         std::vector< NodeID > map;
113         cleanup->GetData( &edges, &map );
114         delete cleanup;
115
116         {
117                 std::vector< unsigned > edgeIDs( numEdges );
118                 for ( unsigned edge = 0; edge < edges.size(); edge++ ) {
119                         if ( edges[edge].data.shortcut )
120                                 continue;
121                         unsigned id = 0;
122                         unsigned otherEdge = edge;
123                         while ( true ) {
124                                 if ( otherEdge == 0 )
125                                         break;
126                                 otherEdge--;
127                                 if ( edges[otherEdge].source != edges[edge].source )
128                                         break;
129                                 if ( edges[otherEdge].target != edges[edge].target )
130                                         continue;
131                                 if ( edges[otherEdge].data.shortcut )
132                                         continue;
133                                 id++;
134                         }
135                         edgeIDs[edges[edge].data.id] = id;
136                 }
137                 importer->SetEdgeIDMap( edgeIDs );
138         }
139
140         std::vector< IRouter::Node > nodes( numNodes );
141         for ( std::vector< IImporter::RoutingNode >::const_iterator i = inputNodes.begin(), iend = inputNodes.end(); i != iend; i++ )
142                 nodes[map[i - inputNodes.begin()]].coordinate = i->coordinate;
143         std::vector< IImporter::RoutingNode >().swap( inputNodes );
144
145         std::vector< IRouter::Node > pathNodes;
146         {
147                 std::vector< IImporter::RoutingNode > edgePaths;
148                 if ( !importer->GetRoutingEdgePaths( &edgePaths ) )
149                         return false;
150                 pathNodes.resize( edgePaths.size() );
151                 for ( unsigned i = 0; i < edgePaths.size(); i++ )
152                         pathNodes[i].coordinate = edgePaths[i].coordinate;
153         }
154
155         if ( !importer->GetRoutingEdges( &inputEdges ) )
156                 return false;
157
158         {
159                 std::vector< QString > inputNames;
160                 if ( !importer->GetRoutingWayNames( &inputNames ) )
161                         return false;
162
163                 QFile nameFile( filename + "_names" );
164                 if ( !openQFile( &nameFile, QIODevice::WriteOnly ) )
165                         return false;
166
167                 std::vector< unsigned > nameMap( inputNames.size() );
168                 for ( unsigned name = 0; name < inputNames.size(); name++ ) {
169                         nameMap[name] = nameFile.pos();
170                         QByteArray buffer = inputNames[name].toUtf8();
171                         buffer.push_back( ( char ) 0 );
172                         nameFile.write( buffer );
173                 }
174
175                 nameFile.close();
176                 nameFile.open( QIODevice::ReadOnly );
177                 const char* test = ( const char* ) nameFile.map( 0, nameFile.size() );
178                 for ( unsigned name = 0; name < inputNames.size(); name++ ) {
179                         QString testName = QString::fromUtf8( test + nameMap[name] );
180                         assert( testName == inputNames[name] );
181                 }
182
183                 for ( unsigned edge = 0; edge < numEdges; edge++ )
184                         inputEdges[edge].nameID = nameMap[inputEdges[edge].nameID];
185         }
186
187         {
188                 std::vector< QString > inputTypes;
189                 if ( !importer->GetRoutingWayTypes( &inputTypes ) )
190                         return false;
191
192                 QFile typeFile( filename + "_types" );
193                 if ( !openQFile( &typeFile, QIODevice::WriteOnly ) )
194                         return false;
195
196                 QStringList typeList;
197                 for ( unsigned type = 0; type < inputTypes.size(); type++ )
198                         typeList.push_back( inputTypes[type] );
199
200                 typeFile.write( typeList.join( ";" ).toUtf8() );
201         }
202
203         for ( std::vector< IImporter::RoutingEdge >::iterator i = inputEdges.begin(), iend = inputEdges.end(); i != iend; i++ ) {
204                 i->source = map[i->source];
205                 i->target = map[i->target];
206         }
207
208         CompressedGraphBuilder* builder = new CompressedGraphBuilder( 1u << m_settings.blockSize, nodes, edges, inputEdges, pathNodes );
209         if ( !builder->run( filename, &map ) )
210                 return false;
211         delete builder;
212
213         importer->SetIDMap( map );
214
215         return true;
216 }
217
218 Q_EXPORT_PLUGIN2( contractionhierarchies, ContractionHierarchies )