bool ContractionHierarchiesClient::LoadData()
{
	QString filename = fileInDirectory( m_directory,"Contraction Hierarchies" );
	UnloadData();

	if ( !m_graph.loadGraph( filename, 1024 * 1024 * 4 ) )
		return false;

	m_namesFile.setFileName( filename + "_names" );
	if ( !openQFile( &m_namesFile, QIODevice::ReadOnly ) )
		return false;
	m_names = ( const char* ) m_namesFile.map( 0, m_namesFile.size() );
	if ( m_names == NULL )
		return false;
	m_namesFile.close();

	m_heapForward = new Heap( m_graph.numberOfNodes() );
	m_heapBackward = new Heap( m_graph.numberOfNodes() );

	QFile typeFile( filename + "_types" );
	if ( !openQFile( &typeFile, QIODevice::ReadOnly ) )
		return false;

	QByteArray buffer = typeFile.readAll();
	QString types = QString::fromUtf8( buffer.constData() );
	m_types = types.split( ';' );

	return true;
}
bool UnicodeTournamentTrieClient::LoadData()
{
	UnloadData();
	QString filename = fileInDirectory( directory, "Unicode Tournament Trie" );
	trieFile = new QFile( filename + "_main" );
	subTrieFile = new QFile( filename + "_sub" );
	dataFile = new QFile( filename + "_ways" );

	if ( !openQFile( trieFile, QIODevice::ReadOnly ) )
		return false;
	if ( !openQFile( subTrieFile, QIODevice::ReadOnly ) )
		return false;
	if ( !openQFile( dataFile, QIODevice::ReadOnly ) )
		return false;

	trieData = ( char* ) trieFile->map( 0, trieFile->size() );
	subTrieData = ( char* ) subTrieFile->map( 0, subTrieFile->size() );

	if ( trieData == NULL ) {
		qDebug( "Failed to Memory Map trie data" );
		return false;
	}
	if ( subTrieData == NULL ) {
		qDebug( "Failed to Memory Map sub trie data" );
		return false;
	}

	return true;
}
Exemplo n.º 3
0
bool OSMRendererClient::load()
{
	if ( m_advancedSettings == NULL )
		m_advancedSettings = new OSMRSettingsDialog();
	advancedSettingsChanged();
	network = new QNetworkAccessManager( this );
	diskCache = new QNetworkDiskCache( this );
	QString cacheDir = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
	if ( cacheDir == "" ) {
		cacheDir = QDesktopServices::storageLocation( QDesktopServices::TempLocation );
		QDir dir( cacheDir );
		dir.mkdir( "osmrenderer" );
		dir.cd( "osmrenderer" );
		cacheDir = dir.path();
	}
	qDebug() << "set disk cache to: " << cacheDir;
	diskCache->setCacheDirectory( cacheDir );
	network->setCache( diskCache );
	connect( network, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)) );
	tileSize = 256;

	QFile settingsFile( fileInDirectory( m_directory, "OSM Renderer" ) + "_settings" );
	if ( !openQFile( &settingsFile, QIODevice::ReadOnly ) )
		return false;

	while ( true ) {
		int zoomLevel;
		if ( settingsFile.read( ( char* ) &zoomLevel, sizeof( zoomLevel ) ) != sizeof( zoomLevel ) )
			break;
		m_zoomLevels.push_back( zoomLevel );
	}

	return true;
}
Exemplo n.º 4
0
	bool SpeedProfile::loadAccessTree( QString filename )
	{
		QFile treeFile( filename );
		if ( !openQFile( &treeFile, QIODevice::ReadOnly ) )
			return false;
		QTextStream stream( &treeFile );

		m_accessTree.clear();
		QString name;
		QString parent;
		// format:
		// name1 parent1
		// name2 parent2 ...
		// the source node has itself as a parent
		// a parent has to be defined before its referenced
		while ( true ) {
			stream >> name >> parent;
			if ( stream.status() != QTextStream::Ok )
				break;

			if ( m_accessTree.contains( name ) ) {
				qCritical() << "Illegal access tree, duplicate entry:" << name;
				return false;
			}

			if ( parent != name && !m_accessTree.contains( parent ) ) {
				qCritical() << "Illegal access tree, parent not yet defined:" << parent;
				return false;
			}

			m_accessTree[name] = parent;
		}

		return true;
	}
Exemplo n.º 5
0
bool MapnikRendererClient::loadTile( int x, int y, int zoom, int /*magnification*/, QPixmap** tile )
{
	const Box& box = m_boxes[zoom];
	if ( x < box.minX || x >= box.maxX )
		return false;
	if ( y < box.minY || y >= box.maxY )
		return false;

	if ( m_fileZoom != zoom ) {
		m_indexFile->close();
		m_tileFile->close();

		QString filename = fileInDirectory( m_directory, "Mapnik Renderer" );
		m_indexFile->setFileName( filename + QString( "_%1_index" ).arg( zoom ) );
		if ( !openQFile( m_indexFile, QIODevice::ReadOnly ) )
			return false;
		m_tileFile->setFileName( filename + QString( "_%1_tiles" ).arg( zoom ) );
		if ( !openQFile( m_tileFile, QIODevice::ReadOnly ) )
			return false;
		m_fileZoom = zoom;
	}

	qint64 indexPosition = qint64( y - box.minY ) * ( box.maxX - box.minX ) + ( x - box.minX );
	m_indexFile->seek( indexPosition * ( sizeof( qint64 ) + sizeof( int ) ) );
	qint64 start;
	int size;
	m_indexFile->read( ( char* ) &start, sizeof( start ) );
	m_indexFile->read( ( char* ) &size, sizeof( size ) );
	if ( size == 0 )
		return false;

	m_tileFile->seek( start );
	QByteArray data = m_tileFile->read( size );
	*tile = new QPixmap( m_tileSize, m_tileSize );
	if ( !( *tile )->loadFromData( data, "PNG" ) ) {
		qDebug() << "Failed to load picture:" << x << y << zoom << " data: (" << start << "-" << start + size << ")";
		delete *tile;
		return false;
	}
	return true;
}
Exemplo n.º 6
0
bool GPSGridClient::LoadData()
{
	UnloadData();
	QString filename = fileInDirectory( directory, "GPSGrid" );
	QFile configFile( filename + "_config" );
	if ( !openQFile( &configFile, QIODevice::ReadOnly ) )
		return false;

	index = new gg::Index( filename + "_index" );
	index->SetCacheSize( 1024 * 1024 * cacheSize / 4 );

	gridFile = new QFile( filename + "_grid" );
	if ( !gridFile->open( QIODevice::ReadOnly ) ) {
		qCritical() << "failed to open file: " << gridFile->fileName();
		return false;
	}

	return true;
}
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;
}
Exemplo n.º 8
0
bool TestImporter::parseDDSG( QString filename )
{
	QString outputPrefix = fileInDirectory( m_outputDirectory, "Test Importer" );

	FileStream edgesData( outputPrefix + "_mapped_edges" );
	FileStream routingCoordinatesData( outputPrefix + "_routing_coordinates" );
	FileStream edgePathsData( outputPrefix + "_paths" );
	FileStream wayRefsData( outputPrefix + "_way_refs" );
	FileStream wayTypesData( outputPrefix + "_way_types" );
	FileStream penaltyData( outputPrefix + "_penalties" );
	FileStream boundingBoxData( outputPrefix + "_bounding_box" );

	if ( !edgesData.open( QIODevice::WriteOnly ) )
		return false;
	if ( !routingCoordinatesData.open( QIODevice::WriteOnly ) )
		return false;
	if ( !edgePathsData.open( QIODevice::WriteOnly ) )
		return false;
	if ( !wayRefsData.open( QIODevice::WriteOnly ) )
		return false;
	if ( !wayTypesData.open( QIODevice::WriteOnly ) )
		return false;
	if ( !penaltyData.open( QIODevice::WriteOnly ) )
		return false;
	if ( !boundingBoxData.open( QIODevice::WriteOnly ) )
		return false;

	QFile ddsgFile( filename );
	if ( !openQFile( &ddsgFile, QIODevice::ReadOnly ) )
		return false;
	QTextStream inputStream( &ddsgFile );

	QString id;
	inputStream >> id;
	if ( id != "d" ) {
		qCritical() << "Not a ddsg file";
		return false;
	}

	wayRefsData << "";
	wayTypesData << "";

	unsigned nodes;
	unsigned edges;
	inputStream >> nodes >> edges;
	std::vector< SimpleEdge > simpleEdges;
	qDebug() << "Test Importer:" << "reading" << nodes << " nodes and" << edges << "edges";
	for ( unsigned i = 0; i < edges; i++ ) {
		unsigned from;
		unsigned to;
		unsigned weight;
		unsigned direction;
		inputStream >> from >> to >> weight >> direction;
		if ( direction == 3 )
			continue;
		if ( from == to )
			continue;
		SimpleEdge newEdge;
		newEdge.source = from;
		newEdge.target = to;
		newEdge.bidirectional = direction == 1;
		newEdge.distance = weight / 10.0;
		newEdge.forward = direction == 1 || direction == 0;
		newEdge.backward = direction == 2 || direction == 0;
		if ( from > to ) {
			std::swap( newEdge.source, newEdge.target );
			std::swap( newEdge.forward, newEdge.backward );
		}
		simpleEdges.push_back( newEdge );
	}

	std::sort( simpleEdges.begin(), simpleEdges.end(), SimpleEdge::sortToMerge );
	unsigned edgesLeft = 1;
	for ( unsigned i = 1; i < simpleEdges.size(); i++ ) {
		SimpleEdge& edge = simpleEdges[i];
		SimpleEdge& otherEdge = simpleEdges[edgesLeft - 1];
		simpleEdges[edgesLeft++] = edge;
		if ( edge.source != otherEdge.source )
			continue;
		if ( edge.target != otherEdge.target )
			continue;
		if ( edge.distance != otherEdge.distance )
			continue;
		edgesLeft--;
		otherEdge.forward |= edge.forward;
		otherEdge.backward |= edge.backward;
	}
	simpleEdges.resize( edgesLeft );

	unsigned biEdges = 0;
	for ( unsigned i = 0; i < simpleEdges.size(); i++ ) {
		if ( !simpleEdges[i].forward ) {
			std::swap( simpleEdges[i].source, simpleEdges[i].target );
			std::swap( simpleEdges[i].forward, simpleEdges[i].backward );
		}
		simpleEdges[i].bidirectional = simpleEdges[i].forward && simpleEdges[i].backward;
		biEdges += simpleEdges[i].bidirectional ? 1 : 0;
		assert( simpleEdges[i].forward );
	}

	qDebug() << "Test Importer:" << biEdges << "bidirectional edges";
	qDebug() << "Test Importer:" << edges - biEdges * 2 << "unidirectional edges";
	qDebug() << "Test Importer:" << edges - edgesLeft << "edges removed";

	std::sort( simpleEdges.begin(), simpleEdges.end() );

	std::vector< char > in( nodes, 0 );
	std::vector< char > out( nodes, 0 );
	std::vector< char > bi( nodes, 0 );
	qDebug() << "Test Importer:" << "writing" << simpleEdges.size() << "edges";
	for ( unsigned i = 0; i < simpleEdges.size(); i++ ) {
		edgesData << simpleEdges[i].source << simpleEdges[i].target << simpleEdges[i].bidirectional << simpleEdges[i].distance;
		edgesData << unsigned( 0 ) << unsigned( 0 ) << unsigned ( 0 ); // name
		edgesData << unsigned( 0 ) << unsigned( 0 ); // path
		edgesData << unsigned( 0 ) << unsigned( 0 ); // address
		edgesData << qint8( out[simpleEdges[i].source]++ ) << qint8( in[simpleEdges[i].target]++ );
		if ( simpleEdges[i].bidirectional ) {
			in[simpleEdges[i].source]++;
			out[simpleEdges[i].target]++;
			bi[simpleEdges[i].source]++;
			bi[simpleEdges[i].target]++;
			assert( in[simpleEdges[i].source] == out[simpleEdges[i].source] );
			assert( in[simpleEdges[i].target] == out[simpleEdges[i].target] );
		}
	}

	long long penalties = 0;
	long long uturns = 0;
	qDebug() << "Test Importer:" << "forbid uturns:" << m_settings.forbidUTurn;
	qDebug() << "Test Importer:" << "uturn penalty:" << m_settings.uTurnPenalty;
	for ( unsigned i = 0; i < nodes; i++ ) {
		routingCoordinatesData << unsigned( 0 ) << unsigned( 0 );
		penaltyData << unsigned( in[i] ) << unsigned( out[i] );
		for ( int from = 0; from < in[i]; from++ ) {
			for ( int to = 0; to < out[i]; to++ ) {
				double penalty = 0;
				if ( from == to && from < bi[i] ) {
					uturns++;
					if ( m_settings.forbidUTurn )
						penalty = -1;
					else
						penalty = m_settings.uTurnPenalty;
				}
				penaltyData << penalty;
				penalties++;
			}
		}
	}
	qDebug() << "Test Importer:" << "wrote" << penalties << "penalties";
	qDebug() << "Test Importer:" << uturns << "uturns";

	return true;
}
bool ContractionHierarchies::Preprocess( IImporter* importer, QString dir )
{
	QString filename = fileInDirectory( dir, "Contraction Hierarchies" );

	std::vector< IImporter::RoutingNode > inputNodes;
	std::vector< IImporter::RoutingEdge > inputEdges;

	if ( !importer->GetRoutingNodes( &inputNodes ) )
		return false;
	if ( !importer->GetRoutingEdges( &inputEdges ) )
		return false;

	unsigned numEdges = inputEdges.size();
	unsigned numNodes = inputNodes.size();

	Contractor* contractor = new Contractor( numNodes, inputEdges );
	std::vector< IImporter::RoutingEdge >().swap( inputEdges );
	contractor->Run();

	std::vector< Contractor::Witness > witnessList;
	contractor->GetWitnessList( witnessList );

	std::vector< ContractionCleanup::Edge > contractedEdges;
	std::vector< ContractionCleanup::Edge > contractedLoops;
	contractor->GetEdges( &contractedEdges );
	contractor->GetLoops( &contractedLoops );
	delete contractor;

	ContractionCleanup* cleanup = new ContractionCleanup( inputNodes.size(), contractedEdges, contractedLoops, witnessList );
	std::vector< ContractionCleanup::Edge >().swap( contractedEdges );
	std::vector< ContractionCleanup::Edge >().swap( contractedLoops );
	std::vector< Contractor::Witness >().swap( witnessList );
	cleanup->Run();

	std::vector< CompressedGraph::Edge > edges;
	std::vector< NodeID > map;
	cleanup->GetData( &edges, &map );
	delete cleanup;

	{
		std::vector< unsigned > edgeIDs( numEdges );
		for ( unsigned edge = 0; edge < edges.size(); edge++ ) {
			if ( edges[edge].data.shortcut )
				continue;
			unsigned id = 0;
			unsigned otherEdge = edge;
			while ( true ) {
				if ( otherEdge == 0 )
					break;
				otherEdge--;
				if ( edges[otherEdge].source != edges[edge].source )
					break;
				if ( edges[otherEdge].target != edges[edge].target )
					continue;
				if ( edges[otherEdge].data.shortcut )
					continue;
				id++;
			}
			edgeIDs[edges[edge].data.id] = id;
		}
		importer->SetEdgeIDMap( edgeIDs );
	}

	std::vector< IRouter::Node > nodes( numNodes );
	for ( std::vector< IImporter::RoutingNode >::const_iterator i = inputNodes.begin(), iend = inputNodes.end(); i != iend; i++ )
		nodes[map[i - inputNodes.begin()]].coordinate = i->coordinate;
	std::vector< IImporter::RoutingNode >().swap( inputNodes );

	std::vector< IRouter::Node > pathNodes;
	{
		std::vector< IImporter::RoutingNode > edgePaths;
		if ( !importer->GetRoutingEdgePaths( &edgePaths ) )
			return false;
		pathNodes.resize( edgePaths.size() );
		for ( unsigned i = 0; i < edgePaths.size(); i++ )
			pathNodes[i].coordinate = edgePaths[i].coordinate;
	}

	if ( !importer->GetRoutingEdges( &inputEdges ) )
		return false;

	{
		std::vector< QString > inputNames;
		if ( !importer->GetRoutingWayNames( &inputNames ) )
			return false;

		QFile nameFile( filename + "_names" );
		if ( !openQFile( &nameFile, QIODevice::WriteOnly ) )
			return false;

		std::vector< unsigned > nameMap( inputNames.size() );
		for ( unsigned name = 0; name < inputNames.size(); name++ ) {
			nameMap[name] = nameFile.pos();
			QByteArray buffer = inputNames[name].toUtf8();
			buffer.push_back( ( char ) 0 );
			nameFile.write( buffer );
		}

		nameFile.close();
		nameFile.open( QIODevice::ReadOnly );
		const char* test = ( const char* ) nameFile.map( 0, nameFile.size() );
		for ( unsigned name = 0; name < inputNames.size(); name++ ) {
			QString testName = QString::fromUtf8( test + nameMap[name] );
			assert( testName == inputNames[name] );
		}

		for ( unsigned edge = 0; edge < numEdges; edge++ )
			inputEdges[edge].nameID = nameMap[inputEdges[edge].nameID];
	}

	{
		std::vector< QString > inputTypes;
		if ( !importer->GetRoutingWayTypes( &inputTypes ) )
			return false;

		QFile typeFile( filename + "_types" );
		if ( !openQFile( &typeFile, QIODevice::WriteOnly ) )
			return false;

		QStringList typeList;
		for ( unsigned type = 0; type < inputTypes.size(); type++ )
			typeList.push_back( inputTypes[type] );

		typeFile.write( typeList.join( ";" ).toUtf8() );
	}

	for ( std::vector< IImporter::RoutingEdge >::iterator i = inputEdges.begin(), iend = inputEdges.end(); i != iend; i++ ) {
		i->source = map[i->source];
		i->target = map[i->target];
	}

	CompressedGraphBuilder* builder = new CompressedGraphBuilder( 1u << m_settings.blockSize, nodes, edges, inputEdges, pathNodes );
	if ( !builder->run( filename, &map ) )
		return false;
	delete builder;

	importer->SetIDMap( map );

	return true;
}
Exemplo n.º 10
0
bool GPSGrid::Preprocess( IImporter* importer, QString dir )
{
	QString filename = fileInDirectory( dir, "GPSGrid" );

	QFile gridFile( filename + "_grid" );
	QFile configFile( filename + "_config" );

	if ( !openQFile( &gridFile, QIODevice::WriteOnly ) )
		return false;
	if ( !openQFile( &configFile, QIODevice::WriteOnly ) )
		return false;

	std::vector< IImporter::RoutingNode > inputNodes;
	std::vector< IImporter::RoutingEdge > inputEdges;
	std::vector< unsigned > nodeIDs;
	std::vector< unsigned > edgeIDs;
	std::vector< IImporter::RoutingNode > edgePaths;

	if ( !importer->GetRoutingNodes( &inputNodes ) )
		return false;
	if ( !importer->GetRoutingEdges( &inputEdges ) )
		return false;
	if ( !importer->GetIDMap( &nodeIDs ) )
		return false;
	if ( !importer->GetEdgeIDMap( &edgeIDs ) )
		return false;
	if ( !importer->GetRoutingEdgePaths( &edgePaths ) )
		return false;

	static const int width = 32 * 32 * 32;

	std::vector< GridImportEdge > grid;

	Timer time;
	for ( std::vector< IImporter::RoutingEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
		std::vector< UnsignedCoordinate > path;
		path.push_back( inputNodes[i->source].coordinate );
		for ( unsigned pathID = 0; pathID < i->pathLength; pathID++ )
			path.push_back( edgePaths[pathID + i->pathID].coordinate );
		path.push_back( inputNodes[i->target].coordinate );

		std::vector< std::pair< unsigned, unsigned > > gridCells;
		for ( unsigned segment = 1; segment < path.size(); segment++ ) {
			ProjectedCoordinate sourceCoordinate = path[segment - 1].ToProjectedCoordinate();
			ProjectedCoordinate targetCoordinate = path[segment].ToProjectedCoordinate();
			sourceCoordinate.x *= width;
			sourceCoordinate.y *= width;
			targetCoordinate.x *= width;
			targetCoordinate.y *= width;

			NodeID minYGrid = floor( sourceCoordinate.y );
			NodeID minXGrid = floor( sourceCoordinate.x );
			NodeID maxYGrid = floor( targetCoordinate.y );
			NodeID maxXGrid = floor( targetCoordinate.x );

			if ( minYGrid > maxYGrid )
				std::swap( minYGrid, maxYGrid );
			if ( minXGrid > maxXGrid )
				std::swap( minXGrid, maxXGrid );

			for ( NodeID yGrid = minYGrid; yGrid <= maxYGrid; ++yGrid ) {
				for ( NodeID xGrid = minXGrid; xGrid <= maxXGrid; ++xGrid ) {
					if ( !clipEdge( sourceCoordinate, targetCoordinate, ProjectedCoordinate( xGrid, yGrid ), ProjectedCoordinate( xGrid + 1, yGrid + 1 ) ) )
						continue;

					gridCells.push_back( std::pair< unsigned, unsigned >( xGrid, yGrid ) );
				}
			}
		}
		std::sort( gridCells.begin(), gridCells.end() );
		gridCells.resize( std::unique( gridCells.begin(), gridCells.end() ) - gridCells.begin() );

		GridImportEdge clippedEdge;
		clippedEdge.edge = i - inputEdges.begin();

		for ( unsigned cell = 0; cell < gridCells.size(); cell++ ) {
			clippedEdge.x = gridCells[cell].first;
			clippedEdge.y = gridCells[cell].second;
			grid.push_back( clippedEdge );
		}
	}
	qDebug() << "GPS Grid: distributed edges:" << time.restart() << "ms";
	qDebug() << "GPS Grid: overhead:" << grid.size() - inputEdges.size() << "duplicated edges";
	qDebug() << "GPS Grid: overhead:" << ( grid.size() - inputEdges.size() ) * 100 / inputEdges.size() << "% duplicated edges";

	std::sort( grid.begin(), grid.end() );
	qDebug() << "GPS Grid: sorted edges:" << time.restart() << "ms";

	std::vector< gg::GridIndex > tempIndex;
	qint64 position = 0;
	for ( std::vector< GridImportEdge >::const_iterator edge = grid.begin(); edge != grid.end(); ) {
		gg::Cell cell;
		gg::GridIndex entry;
		entry.x = edge->x;
		entry.y = edge->y;
		entry.position = position;

		tempIndex.push_back( entry );
		do {
			const IImporter::RoutingEdge& originalEdge = inputEdges[edge->edge];
			gg::Cell::Edge newEdge;
			newEdge.source = nodeIDs[originalEdge.source];
			newEdge.target = nodeIDs[originalEdge.target];
			newEdge.edgeID = edgeIDs[edge->edge];
			newEdge.bidirectional = originalEdge.bidirectional;
			newEdge.pathID = cell.coordinates.size();
			newEdge.pathLength = 2 + originalEdge.pathLength;
			cell.coordinates.push_back( inputNodes[originalEdge.source].coordinate );
			for ( unsigned pathID = 0; pathID < originalEdge.pathLength; pathID++ )
				cell.coordinates.push_back( edgePaths[pathID + originalEdge.pathID].coordinate );
			cell.coordinates.push_back( inputNodes[originalEdge.target].coordinate );
			cell.edges.push_back( newEdge );
			edge++;
		} while ( edge != grid.end() && edge->x == entry.x && edge->y == entry.y );

		ProjectedCoordinate min( ( double ) entry.x / width, ( double ) entry.y / width );
		ProjectedCoordinate max( ( double ) ( entry.x + 1 ) / width, ( double ) ( entry.y + 1 ) / width );

		unsigned maxSize = cell.edges.size() * sizeof( gg::Cell::Edge ) * 2 + cell.coordinates.size() * sizeof( UnsignedCoordinate ) * 2 + 100;
		unsigned char* buffer = new unsigned char[maxSize];
		memset( buffer, 0, maxSize );
		int size = cell.write( buffer, UnsignedCoordinate( min ), UnsignedCoordinate( max ) );
		assert( size < ( int ) maxSize );

#ifndef NDEBUG
		gg::Cell unpackCell;
		unpackCell.read( buffer, UnsignedCoordinate( min ), UnsignedCoordinate( max ) );
		assert( unpackCell == cell );
#endif

		gridFile.write( ( const char* ) &size, sizeof( size ) );
		gridFile.write( ( const char* ) buffer, size );

		delete[] buffer;
		position += size + sizeof( size );
	}
	qDebug() << "GPS Grid: wrote cells:" << time.restart() << "ms";

	gg::Index::Create( filename + "_index", tempIndex );
	qDebug() << "GPS Grid: created index:" << time.restart() << "ms";

	return true;
}
Exemplo n.º 11
0
bool MapnikRenderer::Preprocess( IImporter* importer, QString dir )
{
	QString filename = fileInDirectory( dir, "Mapnik Renderer" );

	try {
		IImporter::BoundingBox box;
		if ( !importer->GetBoundingBox( &box ) )
			return false;
		std::vector< IImporter::RoutingEdge > inputEdges;
		std::vector< IImporter::RoutingNode > inputNodes;
		std::vector< IImporter::RoutingNode > inputPaths;
		if ( m_settings.deleteTiles ) {
			if ( !importer->GetRoutingEdges( &inputEdges ) ) {
				qCritical() << "Mapnik Renderer: failed to read routing edges";
				return false;
			}
			if ( !importer->GetRoutingNodes( &inputNodes ) ) {
				qCritical() << "Mapnik Renderer: failed to read routing nodes";
				return false;
			}
			if ( !importer->GetRoutingEdgePaths( &inputPaths ) ) {
				qCritical() << "Mapnik Renderer: failed to read routing paths";
			}
		}

		Timer time;

		mapnik::datasource_cache::instance().register_datasources( m_settings.plugins.toLatin1().constData() );
		QDir fonts( m_settings.fonts );
		mapnik::projection projection( "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over" );
		mapnik::freetype_engine::register_font( fonts.filePath( "DejaVuSans.ttf" ).toLatin1().constData() );
		mapnik::freetype_engine::register_font( fonts.filePath( "DejaVuSans-Bold.ttf" ).toLatin1().constData() );
		mapnik::freetype_engine::register_font( fonts.filePath( "DejaVuSans-Oblique.ttf" ).toLatin1().constData() );
		mapnik::freetype_engine::register_font( fonts.filePath( "DejaVuSans-BoldOblique.ttf" ).toLatin1().constData() );

		qDebug() << "Mapnik Renderer: initialized mapnik connection:" << time.restart() << "ms";

		int numThreads = omp_get_max_threads();
		qDebug() << "Mapnik Renderer: using" << numThreads << "threads";

		qDebug() << "Mapnik Renderer: x: " << box.min.x << "-" << box.max.x;
		qDebug() << "Mapnik Renderer: y: " << box.min.y << "-" << box.max.y;

		FileStream configData( filename );
		if ( !configData.open( QIODevice::WriteOnly ) )
			return false;

		configData << quint32( m_settings.tileSize ) << quint32( m_settings.zoomLevels.size() );

		long long tilesSkipped = 0;
		long long tiles = 0;
		long long metaTilesRendered = 0;
		long long pngcrushSaved = 0;

		std::vector< ZoomInfo > zoomInfo( m_settings.zoomLevels.size() );
		std::vector< MetaTile > tasks;

		for ( int zoomLevel = 0; zoomLevel < ( int ) m_settings.zoomLevels.size(); zoomLevel++ ) {
			ZoomInfo& info = zoomInfo[zoomLevel];
			int zoom = m_settings.zoomLevels[zoomLevel];

			info.minX = box.min.GetTileX( zoom );
			info.maxX = box.max.GetTileX( zoom ) + 1;
			info.minY = box.min.GetTileY( zoom );
			info.maxY = box.max.GetTileY( zoom ) + 1;

			if ( zoom <= m_settings.fullZoom ) {
				info.minX = info.minY = 0;
				info.maxX = info.maxY = 1 << zoom;
			} else {
				info.minX = std::max( 0 , info.minX - m_settings.tileMargin );
				info.maxX = std::min ( 1 << zoom, info.maxX + m_settings.tileMargin );
				info.minY = std::max( 0, info.minY - m_settings.tileMargin );
				info.maxY = std::min ( 1 << zoom, info.maxY + m_settings.tileMargin );
			}

			tiles += ( info.maxX - info.minX ) * ( info.maxY - info.minY );
			qDebug() << "Mapnik Renderer: [" << zoom << "] x:" << info.minX << "-" << info.maxX << "; y:" << info.minY << "-" << info.maxY;
			configData << quint32( zoom ) << quint32( info.minX ) << quint32( info.maxX ) << quint32( info.minY ) << quint32( info.maxY );

			int numberOfTiles = ( info.maxX - info.minX ) * ( info.maxY - info.minY );
			IndexElement dummyIndex;
			dummyIndex.start = dummyIndex.size = 0;
			info.index.resize( numberOfTiles, dummyIndex );

			std::vector< UnsignedCoordinate > path;
			for ( std::vector< IImporter::RoutingEdge >::const_iterator i = inputEdges.begin(), e = inputEdges.end(); i != e; ++i ) {
				path.push_back( inputNodes[i->source].coordinate );
				for ( int pathID = 0; pathID < i->pathLength; pathID++ )
					path.push_back( inputPaths[pathID + i->pathID].coordinate );
				path.push_back( inputNodes[i->target].coordinate );

				for ( unsigned edge = 0; edge < path.size(); edge++ ) {
					int sourceX = path[edge].GetTileX( zoom );
					int sourceY = path[edge].GetTileY( zoom );
					int targetX = path[edge].GetTileX( zoom );
					int targetY = path[edge].GetTileY( zoom );
					if ( sourceX > targetX )
						std::swap( sourceX, targetX );
					if ( sourceY > targetY )
						std::swap( sourceY, targetY );
					sourceX = std::max( sourceX, info.minX );
					sourceX = std::min( sourceX, info.maxX - 1 );
					sourceY = std::max( sourceY, info.minY );
					sourceY = std::min( sourceY, info.maxY - 1 );
					targetX = std::max( targetX, info.minX );
					targetX = std::min( targetX, info.maxX - 1 );
					targetY = std::max( targetY, info.minY );
					targetY = std::min( targetY, info.maxY - 1 );
					for ( int x = sourceX; x <= targetX; ++x )
						for ( int y = sourceY; y <= targetY; ++y )
							info.index[( x - info.minX ) + ( y - info.minY ) * ( info.maxX - info.minX )].size = 1;
				}

				path.clear();
			}

			info.tilesFile = new QFile( filename + QString( "_%1_tiles" ).arg( zoom ) );
			if ( !openQFile( info.tilesFile, QIODevice::WriteOnly ) )
				return false;

			for ( int x = info.minX; x < info.maxX; x+= m_settings.metaTileSize ) {
				int metaTileSizeX = std::min( m_settings.metaTileSize, info.maxX - x );
				for ( int y = info.minY; y < info.maxY; y+= m_settings.metaTileSize ) {
					int metaTileSizeY = std::min( m_settings.metaTileSize, info.maxY - y );
					MetaTile tile;
					tile.zoom = zoomLevel;
					tile.x = x;
					tile.y = y;
					tile.metaTileSizeX = metaTileSizeX;
					tile.metaTileSizeY = metaTileSizeY;
					tasks.push_back( tile );
				}
			}
		}


#pragma omp parallel
		{
			int threadID = omp_get_thread_num();
			const int metaTileSize = m_settings.metaTileSize * m_settings.tileSize + 2 * m_settings.margin;

			mapnik::Map map;
			mapnik::image_32 image( metaTileSize, metaTileSize );
			QTemporaryFile tempOut;
			QTemporaryFile tempIn;
			mapnik::load_map( map, m_settings.theme.toLocal8Bit().constData() );

#pragma omp for schedule( dynamic )
			for ( int i = 0; i < ( int ) tasks.size(); i++ ) {

				int metaTileSizeX = tasks[i].metaTileSizeX;
				int metaTileSizeY = tasks[i].metaTileSizeY;
				int x = tasks[i].x;
				int y = tasks[i].y;
				int zoomLevel = tasks[i].zoom;
				int zoom = m_settings.zoomLevels[zoomLevel];
				ZoomInfo& info = zoomInfo[zoomLevel];

				map.resize( metaTileSizeX * m_settings.tileSize + 2 * m_settings.margin, metaTileSizeY * m_settings.tileSize + 2 * m_settings.margin );

				ProjectedCoordinate drawTopLeft( x - 1.0 * m_settings.margin / m_settings.tileSize, y - 1.0 * m_settings.margin / m_settings.tileSize, zoom );
				ProjectedCoordinate drawBottomRight( x + metaTileSizeX + 1.0 * m_settings.margin / m_settings.tileSize, y + metaTileSizeY + 1.0 * m_settings.margin / m_settings.tileSize, zoom );
				GPSCoordinate drawTopLeftGPS = drawTopLeft.ToGPSCoordinate();
				GPSCoordinate drawBottomRightGPS = drawBottomRight.ToGPSCoordinate();
				projection.forward( drawTopLeftGPS.longitude, drawBottomRightGPS.latitude );
				projection.forward( drawBottomRightGPS.longitude, drawTopLeftGPS.latitude );
				mapnik::box2d<double> boundingBox( drawTopLeftGPS.longitude, drawTopLeftGPS.latitude, drawBottomRightGPS.longitude, drawBottomRightGPS.latitude );
				map.zoom_to_box( boundingBox );
				mapnik::agg_renderer<mapnik::image_32> renderer( map, image );
				renderer.apply();

				std::string data;
				int skipped = 0;
				int saved = 0;
				for ( int subX = 0; subX < metaTileSizeX; ++subX ) {
					for ( int subY = 0; subY < metaTileSizeY; ++subY ) {
						int indexNumber = ( y + subY - info.minY ) * ( info.maxX - info.minX ) + x + subX - info.minX;
						mapnik::image_view<mapnik::image_data_32> view = image.get_view( subX * m_settings.tileSize + m_settings.margin, subY * m_settings.tileSize + m_settings.margin, m_settings.tileSize, m_settings.tileSize );
						std::string result;
						if ( !m_settings.deleteTiles || info.index[( x + subX - info.minX ) + ( y + subY - info.minY ) * ( info.maxX - info.minX )].size == 1 ) {
							if ( m_settings.reduceColors )
								result = mapnik::save_to_string( view, "png256" );
							else
								result = mapnik::save_to_string( view, "png" );

							if ( m_settings.pngcrush ) {
								tempOut.open();
								tempOut.write( result.data(), result.size() );
								tempOut.flush();
								tempIn.open();
								pclose( popen( ( "pngcrush " + tempOut.fileName() + " " + tempIn.fileName() ).toUtf8().constData(), "r" ) );
								QByteArray buffer = tempIn.readAll();
								tempIn.close();
								tempOut.close();
								if ( buffer.size() != 0 && buffer.size() < ( int ) result.size() ) {
									saved += result.size() - buffer.size();
									result.assign( buffer.constData(), buffer.size() );
								}
							}
						}

						info.index[indexNumber].start = data.size();
						info.index[indexNumber].size = result.size();
						data += result;
					}
				}

				qint64 position;
#pragma omp critical
				{
					position = info.tilesFile->pos();
					info.tilesFile->write( data.data(), data.size() );

					metaTilesRendered++;
					tilesSkipped += skipped;
					pngcrushSaved += saved;
					qDebug() << "Mapnik Renderer: [" << zoom << "], thread" << threadID << ", metatiles:" << metaTilesRendered << "/" << tasks.size();
				}

				for ( int subX = 0; subX < metaTileSizeX; ++subX ) {
					for ( int subY = 0; subY < metaTileSizeY; ++subY ) {
						int indexNumber = ( y + subY - info.minY ) * ( info.maxX - info.minX ) + x + subX - info.minX;
						info.index[indexNumber].start += position;
					}
				}
			}
		}

		for ( int zoomLevel = 0; zoomLevel < ( int ) m_settings.zoomLevels.size(); zoomLevel++ ) {
			const ZoomInfo& info = zoomInfo[zoomLevel];
			int zoom = m_settings.zoomLevels[zoomLevel];
			QFile indexFile( filename + QString( "_%1_index" ).arg( zoom ) );
			if ( !openQFile( &indexFile, QIODevice::WriteOnly ) )
				return false;
			for ( int i = 0; i < ( int ) info.index.size(); i++ ) {
				indexFile.write( ( const char* ) &info.index[i].start, sizeof( info.index[i].start ) );
				indexFile.write( ( const char* ) &info.index[i].size, sizeof( info.index[i].size ) );
			}
			delete info.tilesFile;
		}

		if ( m_settings.deleteTiles )
			qDebug() << "Mapnik Renderer: removed" << tilesSkipped << "tiles";
		if ( m_settings.pngcrush )
			qDebug() << "Mapnik Renderer: PNGcrush saved" << pngcrushSaved / 1024 / 1024 << "MB";

		qDebug() << "Mapnik Renderer: finished:" << time.restart() << "ms";

	} catch ( const mapnik::config_error & ex ) {
		qCritical( "Mapnik Renderer: ### Configuration error: %s", ex.what() );
		return false;
	} catch ( const std::exception & ex ) {
		qCritical( "Mapnik Renderer: ### STD error: %s", ex.what() );
		return false;
	} catch ( ... ) {
		qCritical( "Mapnik Renderer: ### Unknown error" );
		return false;
	}
	return true;
}