void rasterize(std::ostream &output, const OsmAnd::EyePiece::Configuration& cfg) #endif { // Obtain and configure rasterization style context OsmAnd::MapStyles stylesCollection; for(auto itStyleFile = cfg.styleFiles.begin(); itStyleFile != cfg.styleFiles.end(); ++itStyleFile) { const auto& styleFile = *itStyleFile; if(!stylesCollection.registerStyle(styleFile.absoluteFilePath())) output << xT("Failed to parse metadata of '") << QStringToStlString(styleFile.fileName()) << xT("' or duplicate style") << std::endl; } std::shared_ptr<const OsmAnd::MapStyle> style; if(!stylesCollection.obtainStyle(cfg.styleName, style)) { output << xT("Failed to resolve style '") << QStringToStlString(cfg.styleName) << xT("'") << std::endl; return; } if(cfg.dumpRules) style->dump(); OsmAnd::ObfsCollection obfsCollection; obfsCollection.watchDirectory(cfg.obfsDir); // Collect all map objects (this should be replaced by something like RasterizerViewport/RasterizerContext) QList< std::shared_ptr<const OsmAnd::Model::MapObject> > mapObjects; OsmAnd::AreaI bbox31( OsmAnd::Utilities::get31TileNumberY(cfg.bbox.top), OsmAnd::Utilities::get31TileNumberX(cfg.bbox.left), OsmAnd::Utilities::get31TileNumberY(cfg.bbox.bottom), OsmAnd::Utilities::get31TileNumberX(cfg.bbox.right) ); const auto& obfDI = obfsCollection.obtainDataInterface(); OsmAnd::MapFoundationType mapFoundation; obfDI->obtainMapObjects(&mapObjects, &mapFoundation, bbox31, cfg.zoom, nullptr); bool basemapAvailable; obfDI->obtainBasemapPresenceFlag(basemapAvailable); // Calculate output size in pixels const auto tileWidth = OsmAnd::Utilities::getTileNumberX(cfg.zoom, cfg.bbox.right) - OsmAnd::Utilities::getTileNumberX(cfg.zoom, cfg.bbox.left); const auto tileHeight = OsmAnd::Utilities::getTileNumberY(cfg.zoom, cfg.bbox.bottom) - OsmAnd::Utilities::getTileNumberY(cfg.zoom, cfg.bbox.top); const auto pixelWidth = qCeil(tileWidth * cfg.tileSide); const auto pixelHeight = qCeil(tileHeight * cfg.tileSide); output << xT("Will rasterize ") << mapObjects.count() << xT(" objects onto ") << pixelWidth << xT("x") << pixelHeight << xT(" bitmap") << std::endl; // Allocate render target SkBitmap renderSurface; renderSurface.setConfig(cfg.is32bit ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config, pixelWidth, pixelHeight); if(!renderSurface.allocPixels()) { output << xT("Failed to allocated render target ") << pixelWidth << xT("x") << pixelHeight; return; } SkDevice renderTarget(renderSurface); // Create render canvas SkCanvas canvas(&renderTarget); // Perform actual rendering OsmAnd::RasterizerEnvironment rasterizerEnv(style, basemapAvailable); OsmAnd::RasterizerContext rasterizerContext; OsmAnd::Rasterizer::prepareContext(rasterizerEnv, rasterizerContext, bbox31, cfg.zoom, cfg.tileSide, cfg.densityFactor, mapFoundation, mapObjects, OsmAnd::PointF(), nullptr); if(cfg.drawMap) OsmAnd::Rasterizer::rasterizeMap(rasterizerEnv, rasterizerContext, true, canvas, nullptr); /*if(cfg.drawText) OsmAnd::Rasterizer::rasterizeText(rasterizerContext, !cfg.drawMap, canvas, nullptr);*/ // Save rendered area if(!cfg.output.isEmpty()) { std::unique_ptr<SkImageEncoder> encoder(CreatePNGImageEncoder()); std::unique_ptr<SkImageEncoder> outputStream(CreatePNGImageEncoder()); encoder->encodeFile(cfg.output.toLocal8Bit(), renderSurface, 100); } return; }
void dump(std::ostream &output, const OsmAnd::Verifier::Configuration& cfg) #endif { OsmAnd::ObfsCollection obfsCollection; for(const auto& obfsDir : cfg.obfDirs) obfsCollection.addDirectory(obfsDir); for(const auto& obfFile : cfg.obfFiles) obfsCollection.addFile(obfFile); const auto dataInterface = obfsCollection.obtainDataInterface(); const auto obfFiles = obfsCollection.getObfFiles(); output << "Will work with these files:" << std::endl; for(const auto& obfFile : obfFiles) output << "\t" << qPrintable(obfFile->filePath) << std::endl; if(cfg.action == OsmAnd::Verifier::Configuration::Action::UniqueMapObjectIds) { const OsmAnd::AreaI entireWorld(0, 0, std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max()); unsigned int lastReportedCount = 0; unsigned int totalDuplicatesCount = 0; for(int zoomLevel = OsmAnd::MinZoomLevel; zoomLevel <= OsmAnd::MaxZoomLevel; zoomLevel++) { output << "Processing " << zoomLevel << " zoom level..." << std::endl; QList< std::shared_ptr<const OsmAnd::Model::MapObject> > duplicateMapObjects; QHash<uint64_t, unsigned int> mapObjectIds; const auto idsCollector = [&mapObjectIds, &lastReportedCount, &output, &totalDuplicatesCount]( const std::shared_ptr<const OsmAnd::ObfMapSectionInfo>& section, const uint64_t mapObjectId, const OsmAnd::AreaI& bbox, const OsmAnd::ZoomLevel firstZoomLevel, const OsmAnd::ZoomLevel lasttZoomLevel) -> bool { const auto itId = mapObjectIds.find(mapObjectId); if(itId != mapObjectIds.end()) { // Increment duplicates counter itId.value()++; totalDuplicatesCount++; return true; } // Insert new entry mapObjectIds.insert(mapObjectId, 0); if(mapObjectIds.size() - lastReportedCount == 10000) { output << "\t... processed 10k map objects, found " << totalDuplicatesCount << " duplicate(s) so far ... " << std::endl; lastReportedCount = mapObjectIds.size(); } return false; }; dataInterface->loadMapObjects(&duplicateMapObjects, nullptr, entireWorld, static_cast<OsmAnd::ZoomLevel>(zoomLevel), nullptr, idsCollector, nullptr); output << "\tProcessed " << mapObjectIds.size() << " map objects."; if(!mapObjectIds.isEmpty()) output << " Found " << totalDuplicatesCount << " duplicate(s) :"; output << std::endl; for(auto itEntry = mapObjectIds.cbegin(); itEntry != mapObjectIds.cend(); ++itEntry) { const auto mapObjectId = itEntry.key(); const auto duplicatesCount = itEntry.value(); if(duplicatesCount == 0) continue; output << "\tMapObject "; if(static_cast<int64_t>(mapObjectId) < 0) { int64_t originalId = -static_cast<int64_t>(static_cast<uint64_t>(-static_cast<int64_t>(mapObjectId)) & 0xFFFFFFFF); output << originalId; } else { output << mapObjectId; } output << " has " << duplicatesCount << " duplicate(s)." << std::endl; } } output << "Totally " << totalDuplicatesCount << " duplicate(s) across all zoom levels" << std::endl; } }