int writeTrie(Trie *triep, int level, FILE *fp) { Trie *tp = triep; static char name_buf[MAX_TRIE_LEVEL+1], *namep; if (tp == TRIE_NULL) return 1; if (tp->n.t_altr != TRIE_NULL) (void) writeTrie(tp->n.t_altr, level, fp); if (level == 0) namep = name_buf; *namep = tp->n.t_char; if (tp->n.t_next == TRIE_NULL) { /* At end of name, so print it out. */ *namep = NUL; (void) fprintf(fp, "%s\n", name_buf); } else { namep++; (void) writeTrie(tp->n.t_next, level+1, fp); namep--; } return 1; }
bool UnicodeTournamentTrie::Preprocess( IImporter* importer, QString dir ) { QString filename = fileInDirectory( dir, "Unicode Tournament Trie" ); QFile subTrieFile( filename + "_sub" ); QFile wayFile( filename + "_ways" ); if ( !openQFile( &subTrieFile, QIODevice::WriteOnly ) ) return false; if ( !openQFile( &wayFile, QIODevice::WriteOnly ) ) return false; std::vector< IImporter::Place > inputPlaces; std::vector< IImporter::Address > inputAddress; std::vector< UnsignedCoordinate > inputWayBuffer; std::vector< QString > inputWayNames; if ( !importer->GetAddressData( &inputPlaces, &inputAddress, &inputWayBuffer, &inputWayNames ) ) return false; Timer time; std::sort( inputAddress.begin(), inputAddress.end() ); qDebug() << "Unicode Tournament Trie: sorted addresses by importance:" << time.restart() << "ms"; std::vector< UnsignedCoordinate > wayBuffer; std::vector< utt::Node > trie( 1 ); unsigned address = 0; // build address name index QMultiHash< unsigned, unsigned > addressByName; for ( ; address < inputAddress.size(); address++ ) { addressByName.insert( inputAddress[address].name, address ); } // compute way lengths QList< unsigned > uniqueNames = addressByName.uniqueKeys(); std::vector< std::pair< double, unsigned > > wayLengths; for ( unsigned name = 0; name < ( unsigned ) uniqueNames.size(); name++ ) { QList< unsigned > segments = addressByName.values( uniqueNames[name] ); double distance = 0; for( unsigned segment = 0; segment < ( unsigned ) segments.size(); segment++ ) { const IImporter::Address segmentAddress = inputAddress[segment]; for ( unsigned coord = 1; coord < segmentAddress.pathLength; ++coord ) { GPSCoordinate sourceGPS = inputWayBuffer[segmentAddress.pathID + coord - 1].ToProjectedCoordinate().ToGPSCoordinate(); GPSCoordinate targetGPS = inputWayBuffer[segmentAddress.pathID + coord].ToProjectedCoordinate().ToGPSCoordinate(); distance += sourceGPS.ApproximateDistance( targetGPS ); } } wayLengths.push_back( std::pair< double, unsigned >( distance, name ) ); } // sort ways by aggregate lengths std::sort( wayLengths.begin(), wayLengths.end() ); std::vector< unsigned > wayImportance( uniqueNames.size() ); for ( unsigned way = 0; way < wayLengths.size(); way++ ) wayImportance[wayLengths[way].second] = way; wayLengths.clear(); std::vector< utt::Node > subTrie( 1 ); for ( unsigned name = 0; name < ( unsigned ) uniqueNames.size(); name++ ) { QList< unsigned > segments = addressByName.values( uniqueNames[name] ); // build edge connector data structures std::vector< EdgeConnector< UnsignedCoordinate>::Edge > connectorEdges; std::vector< unsigned > resultSegments; std::vector< unsigned > resultSegmentDescriptions; std::vector< bool > resultReversed; for ( unsigned segment = 0; segment < ( unsigned ) segments.size(); segment++ ) { const IImporter::Address& segmentAddress = inputAddress[segments[segment]]; EdgeConnector< UnsignedCoordinate >::Edge newEdge; newEdge.source = inputWayBuffer[segmentAddress.pathID]; newEdge.target = inputWayBuffer[segmentAddress.pathID + segmentAddress.pathLength - 1]; newEdge.reverseable = true; connectorEdges.push_back( newEdge ); } EdgeConnector< UnsignedCoordinate >::run( &resultSegments, &resultSegmentDescriptions, &resultReversed, connectorEdges ); // string places with the same name together unsigned nextID = 0; for ( unsigned segment = 0; segment < resultSegments.size(); segment++ ) { utt::Data subEntry; subEntry.start = wayBuffer.size(); for ( unsigned description = 0; description < resultSegments[segment]; description++ ) { unsigned segmentID = resultSegmentDescriptions[nextID + description]; const IImporter::Address& segmentAddress = inputAddress[segments[segmentID]]; std::vector< UnsignedCoordinate > path; for ( unsigned pathID = 0; pathID < segmentAddress.pathLength; pathID++ ) path.push_back( inputWayBuffer[pathID + segmentAddress.pathID]); if ( resultReversed[segmentID] ) std::reverse( path.begin(), path.end() ); int skipFirst = description == 0 ? 0 : 1; assert( skipFirst == 0 || wayBuffer.back() == path.front() ); wayBuffer.insert( wayBuffer.end(), path.begin() + skipFirst, path.end() ); } utt::PlaceData placeData; placeData.name = inputPlaces[inputAddress[segments[resultSegmentDescriptions[nextID]]].nearPlace].name; subEntry.length = wayBuffer.size() - subEntry.start; insert( &subTrie, wayImportance[name], inputWayNames[uniqueNames[name]], subEntry, placeData ); nextID += resultSegments[segment]; } } writeTrie( &subTrie, subTrieFile ); assert( address == inputAddress.size() ); qDebug() << "Unicode Tournament Trie: build tries and tournament trees:" << time.restart() << "ms"; for ( std::vector< UnsignedCoordinate >::const_iterator i = wayBuffer.begin(), e = wayBuffer.end(); i != e; ++i ) { wayFile.write( ( char* ) &i->x, sizeof( i->x ) ); wayFile.write( ( char* ) &i->y, sizeof( i->y ) ); } qDebug() << "Unicode Tournament Trie: wrote ways:" << time.restart() << "ms"; return true; }