int display_title(View * view) { View *title; char left[100], center[100]; int size; *left = 0; *center = 0; if (view->cell.configured) { sprintf(center, "%s (mag %.1f)", view->cell.name, magnification(view)); } if (view == VIEW_MAP1) { sprintf(left, "%s", G_location()); title = VIEW_TITLE1; } else if (view == VIEW_MAP1_ZOOM) { title = VIEW_TITLE1_ZOOM; } if (view == VIEW_MAP2) { sprintf(left, "%s", G_location()); title = VIEW_TITLE2; } else if (view == VIEW_MAP2_ZOOM) { title = VIEW_TITLE2_ZOOM; } Erase_view(title); R_standard_color(WHITE); size = title->nrows - 4; R_text_size(size, size); Text(left, title->top, title->bottom, title->left, title->right, 2); if (*center) { R_standard_color(YELLOW); Text(center, title->top, title->bottom, (title->left + title->right - Text_width(center)) / 2, title->right, 2); } return 0; }
static int zoom1(int x, int y) { /* called by Input_pointer */ int top, bottom, left, right; int n, row, col; int nrows, ncols; struct Cell_head cellhd; int mag; double magnification(); double north, south, east, west; if (In_view(pick_view = VIEW_MAP1, x, y)) { main_view = VIEW_MAP1; zoom_view = VIEW_MAP1_ZOOM; target_flag = 0; } else if (In_view(pick_view = VIEW_MAP2, x, y)) { if (!pick_view->cell.configured) return 0; /* ignore the mouse event */ main_view = VIEW_MAP2; zoom_view = VIEW_MAP2_ZOOM; target_flag = 1; } else if (In_view(pick_view = VIEW_MAP1_ZOOM, x, y)) { if (!pick_view->cell.configured) return 0; /* ignore the mouse event */ main_view = VIEW_MAP1; zoom_view = VIEW_MAP1_ZOOM; target_flag = 0; } else if (In_view(pick_view = VIEW_MAP2_ZOOM, x, y)) { if (!pick_view->cell.configured) return 0; /* ignore the mouse event */ main_view = VIEW_MAP2; zoom_view = VIEW_MAP2_ZOOM; target_flag = 1; } else return 0; /* ignore the mouse event */ if (!pick_view->cell.configured) return 0; /* just to be sure */ /* * make sure point is within edges of image as well */ if (x <= pick_view->cell.left) return 0; if (x >= pick_view->cell.right) return 0; if (y <= pick_view->cell.top) return 0; if (y >= pick_view->cell.bottom) return 0; /* * ok, erase menu messages */ Menu_msg(""); /* determine magnification of zoom */ if (zoom_view->cell.configured) { if (zoom_view == pick_view) mag = floor(magnification(zoom_view) + 1.0) + .1; else mag = ceil(magnification(zoom_view)) + .1; } else { mag = floor(magnification(main_view) + 1.0) + .1; } if (!ask_magnification(&mag)) return 1; /* * Determine the the zoom window (ie, cellhd) */ G_copy(&cellhd, &main_view->cell.head, sizeof(cellhd)); cellhd.ns_res = main_view->cell.ns_res / mag; cellhd.ew_res = main_view->cell.ew_res / mag; cellhd.cols = (cellhd.east - cellhd.west) / cellhd.ew_res; cellhd.rows = (cellhd.north - cellhd.south) / cellhd.ns_res; /* convert x,y to col,row */ col = view_to_col(pick_view, x); east = col_to_easting(&pick_view->cell.head, col, 0.5); col = easting_to_col(&cellhd, east); row = view_to_row(pick_view, y); north = row_to_northing(&pick_view->cell.head, row, 0.5); row = northing_to_row(&cellhd, north); ncols = zoom_view->ncols; nrows = zoom_view->nrows; n = cellhd.cols - col; if (n > col) n = col; if (n + n + 1 >= ncols) { n = ncols / 2; if (n + n + 1 >= ncols) n--; } left = col - n; right = col + n; n = cellhd.rows - row; if (n > row) n = row; if (n + n + 1 >= nrows) { n = nrows / 2; if (n + n + 1 >= nrows) n--; } top = row - n; bottom = row + n; north = row_to_northing(&cellhd, top, 0.0); west = col_to_easting(&cellhd, left, 0.0); south = row_to_northing(&cellhd, bottom, 1.0); east = col_to_easting(&cellhd, right, 1.0); cellhd.north = north; cellhd.south = south; cellhd.east = east; cellhd.west = west; cellhd.rows = (cellhd.north - cellhd.south) / cellhd.ns_res; cellhd.cols = (cellhd.east - cellhd.west) / cellhd.ew_res; /* * Outline the zoom window on the main map * Turn previous one to grey. */ if (zoom_view->cell.configured) { R_standard_color(GREY); Outline_cellhd(main_view, &zoom_view->cell.head); } R_standard_color(RED); Outline_cellhd(main_view, &cellhd); /* * zoom */ if (target_flag) select_target_env(); G_copy(&zoom_view->cell.head, &cellhd, sizeof(cellhd)); Configure_view(zoom_view, pick_view->cell.name, pick_view->cell.mapset, pick_view->cell.ns_res, pick_view->cell.ew_res); drawcell(zoom_view); select_current_env(); display_points(1); return 1; /* pop back */ }
int main(int argc, char* argv[]) { osmscout::CmdLineParser argParser("PerformanceTest", argc,argv); Arguments args; osmscout::DatabaseParameter databaseParameter; argParser.AddOption(osmscout::CmdLineFlag([&args](const bool& value) { args.help=value; }), std::vector<std::string>{"h","help"}, "Display help", true); argParser.AddOption(osmscout::CmdLineFlag([&args](const bool& value) { args.debug=value; }), "debug", "Enable debug output", false); argParser.AddOption(osmscout::CmdLineUIntOption([&args](const unsigned int& value) { args.startZoom=osmscout::MagnificationLevel(value); }), "start-zoom", "Start zoom, default: " + std::to_string(args.startZoom.Get()), false); argParser.AddOption(osmscout::CmdLineUIntOption([&args](const unsigned int& value) { args.endZoom=osmscout::MagnificationLevel(value); }), "end-zoom", "End zoom, default: " + std::to_string(args.endZoom.Get()), false); argParser.AddOption(osmscout::CmdLineUIntOption([&args](const unsigned int& value) { args.tileDimension=std::make_tuple(value, std::get<1>(args.tileDimension)); }), "tile-width", "Tile width, default: " + std::to_string(std::get<0>(args.tileDimension)), false); argParser.AddOption(osmscout::CmdLineUIntOption([&args](const unsigned int& value) { args.tileDimension=std::make_tuple(std::get<0>(args.tileDimension), value); }), "tile-height", "Tile height, default: " + std::to_string(std::get<1>(args.tileDimension)), false); argParser.AddOption(osmscout::CmdLineStringOption([&args](const std::string& value) { args.driver = value; }), "driver", "Rendering driver (cairo|Qt|ag|opengl|noop|none), default: " + args.driver, false); argParser.AddOption(osmscout::CmdLineDoubleOption([&args](const double& value) { if (value > 0) { args.dpi = value; } else { std::cerr << "DPI can't be negative or zero" << std::endl; } }), "dpi", "Rendering DPI, default: " + std::to_string(args.dpi), false); argParser.AddOption(osmscout::CmdLineUIntOption([&args](const unsigned int& value) { args.drawRepeat = value; }), "draw-repeat", "Repeat every draw call, default: " + std::to_string(args.drawRepeat), false); argParser.AddOption(osmscout::CmdLineUIntOption([&args](const unsigned int& value) { args.loadRepeat = value; }), "load-repeat", "Repeat every load call, default: " + std::to_string(args.loadRepeat), false); argParser.AddOption(osmscout::CmdLineFlag([&args](const bool& value) { args.flushCache=value; }), "flush-cache", "Flush data caches after each data load, default: " + std::to_string(args.flushCache), false); argParser.AddOption(osmscout::CmdLineFlag([&args](const bool& value) { args.flushDiskCache=value; }), "flush-disk", "Flush system disk caches after each data load, default: " + std::to_string(args.flushDiskCache) + " (It work just on Linux with admin rights.)", false); argParser.AddOption(osmscout::CmdLineUIntOption([&databaseParameter](const unsigned int& value) { databaseParameter.SetNodeDataCacheSize(value); }), "cache-nodes", "Cache size for nodes, default: " + std::to_string(databaseParameter.GetNodeDataCacheSize()), false); argParser.AddOption(osmscout::CmdLineUIntOption([&databaseParameter](const unsigned int& value) { databaseParameter.SetWayDataCacheSize(value); }), "cache-ways", "Cache size for ways, default: " + std::to_string(databaseParameter.GetWayDataCacheSize()), false); argParser.AddOption(osmscout::CmdLineUIntOption([&databaseParameter](const unsigned int& value) { databaseParameter.SetAreaDataCacheSize(value); }), "cache-areas", "Cache size for areas, default: " + std::to_string(databaseParameter.GetAreaDataCacheSize()), false); #if defined(HAVE_LIB_GPERFTOOLS) argParser.AddOption(osmscout::CmdLineStringOption([&args](const std::string& value) { args.heapProfilePrefix = value; args.heapProfile = !args.heapProfilePrefix.empty(); }), "heap-profile", "GPerf heap profile prefix, profiler is disabled by default", false); #endif argParser.AddPositional(osmscout::CmdLineStringOption([&args](const std::string& value) { args.databaseDirectory=value; }), "databaseDir", "Database directory"); argParser.AddPositional(osmscout::CmdLineStringOption([&args](const std::string& value) { args.style=value; }), "stylesheet", "Map stylesheet"); argParser.AddPositional(osmscout::CmdLineGeoCoordOption([&args](const osmscout::GeoCoord& coord) { args.coordTopLeft = coord; }), "lat_top lon_left", "Bounding box top-left coordinate"); argParser.AddPositional(osmscout::CmdLineGeoCoordOption([&args](const osmscout::GeoCoord& coord) { args.coordBottomRight = coord; }), "lat_bottom lon_right", "Bounding box bottom-right coordinate"); osmscout::CmdLineParseResult argResult=argParser.Parse(); if (argResult.HasError()) { std::cerr << "ERROR: " << argResult.GetErrorDescription() << std::endl; std::cout << argParser.GetHelp() << std::endl; return 1; } else if (args.help) { std::cout << argParser.GetHelp() << std::endl; return 0; } osmscout::log.Debug(args.debug); //databaseParameter.SetDebugPerformance(true); osmscout::DatabaseRef database=std::make_shared<osmscout::Database>(databaseParameter); osmscout::MapServiceRef mapService=std::make_shared<osmscout::MapService>(database); if (!database->Open(args.databaseDirectory)) { std::cerr << "Cannot open database" << std::endl; return 1; } osmscout::StyleConfigRef styleConfig=std::make_shared<osmscout::StyleConfig>(database->GetTypeConfig()); if (!styleConfig->Load(args.style)) { std::cerr << "Cannot open style" << std::endl; return 1; } PerformanceTestBackendPtr backendPtr = PrepareBackend(argc, argv, args, styleConfig); if (!backendPtr){ return 1; } #if defined(HAVE_LIB_GPERFTOOLS) if (args.heapProfile){ HeapProfilerStart(args.heapProfilePrefix.c_str()); } #endif osmscout::TileProjection projection; osmscout::MapParameter drawParameter; osmscout::AreaSearchParameter searchParameter; std::list<LevelStats> statistics; // TODO: Use some way to find a valid font on the system (Agg display a ton of messages otherwise) drawParameter.SetFontName("/usr/share/fonts/TTF/DejaVuSans.ttf"); searchParameter.SetUseMultithreading(true); for (osmscout::MagnificationLevel level=osmscout::MagnificationLevel(std::min(args.startZoom,args.endZoom)); level<=osmscout::MagnificationLevel(std::max(args.startZoom,args.endZoom)); level++) { LevelStats stats(level.Get()); osmscout::Magnification magnification(level); osmscout::OSMTileId tileA(osmscout::OSMTileId::GetOSMTile(magnification, osmscout::GeoCoord(args.LatBottom(),args.LonLeft()))); osmscout::OSMTileId tileB(osmscout::OSMTileId::GetOSMTile(magnification, osmscout::GeoCoord(args.LatTop(),args.LonRight()))); osmscout::OSMTileIdBox tileArea(tileA,tileB); std::cout << "----------" << std::endl; std::cout << "Drawing level " << level << ", " << tileArea.GetCount() << " tiles " << tileArea.GetDisplayText() << std::endl; size_t current=1; size_t tileCount=tileArea.GetCount(); size_t delta=tileCount/20; if (delta==0) { delta=1; } for (const auto& tile : tileArea) { osmscout::MapData data; osmscout::OSMTileIdBox tileBox(osmscout::OSMTileId(tile.GetX()-1,tile.GetY()-1), osmscout::OSMTileId(tile.GetX()+1,tile.GetY()+1)); osmscout::GeoBox boundingBox; if ((current % delta)==0) { std::cout << current*100/tileCount << "% " << current; if (stats.tileCount>0) { std::cout << " " << stats.dbTotalTime/stats.tileCount; std::cout << " " << stats.drawTotalTime/stats.tileCount; } std::cout << std::endl; } projection.Set(tile, magnification, args.dpi, args.TileWidth(), args.TileHeight()); projection.GetDimensions(boundingBox); projection.SetLinearInterpolationUsage(level.Get() >= 10); for (size_t i=0; i<args.loadRepeat; i++) { data.nodes.clear(); data.ways.clear(); data.areas.clear(); osmscout::StopClock dbTimer; osmscout::GeoBox dataBoundingBox(tileBox.GetBoundingBox(magnification)); std::list<osmscout::TileRef> tiles; // set cache size almost unlimited, // for better estimate of peak memory usage by tile loading mapService->SetCacheSize(10000000); mapService->LookupTiles(magnification, dataBoundingBox, tiles); mapService->LoadMissingTileData(searchParameter, *styleConfig, tiles); mapService->AddTileDataToMapData(tiles, data); #if defined(HAVE_LIB_GPERFTOOLS) if (args.heapProfile) { std::ostringstream buff; buff << "load-" << level << "-" << tile.GetX() << "-" << tile.GetY(); HeapProfilerDump(buff.str().c_str()); } struct mallinfo alloc_info = tc_mallinfo(); #else #if defined(HAVE_MALLINFO) struct mallinfo alloc_info = mallinfo(); #endif #endif #if defined(HAVE_MALLINFO) || defined(HAVE_LIB_GPERFTOOLS) std::cout << "memory usage: " << formatAlloc(alloc_info.uordblks) << std::endl; stats.allocMax = std::max(stats.allocMax, (double) alloc_info.uordblks); stats.allocSum = stats.allocSum + (double) alloc_info.uordblks; #endif // set cache size back to default mapService->SetCacheSize(25); dbTimer.Stop(); double dbTime = dbTimer.GetMilliseconds(); stats.dbMinTime = std::min(stats.dbMinTime, dbTime); stats.dbMaxTime = std::max(stats.dbMaxTime, dbTime); stats.dbTotalTime += dbTime; if (args.flushCache) { tiles.clear(); // following flush method removes only tiles with use_count() == 1 mapService->FlushTileCache(); // simplest way howto flush database caches is close it and open again database->Close(); if (!database->Open(args.databaseDirectory)) { std::cerr << "Cannot open database" << std::endl; return 1; } } if (args.flushDiskCache) { // Linux specific if (osmscout::ExistsInFilesystem("/proc/sys/vm/drop_caches")){ osmscout::FileWriter f; try { f.Open("/proc/sys/vm/drop_caches"); f.Write(std::string("3")); f.Close(); }catch(const osmscout::IOException &e){ std::cerr << "Can't flush disk cache: " << e.what() << std::endl; } }else{ std::cerr << "Can't flush disk cache, \"/proc/sys/vm/drop_caches\" file don't exists" << std::endl; } } } stats.nodeCount+=data.nodes.size(); stats.wayCount+=data.ways.size(); stats.areaCount+=data.areas.size(); stats.tileCount++; for (size_t i=0; i<args.drawRepeat; i++) { osmscout::StopClock drawTimer; backendPtr->DrawMap(projection, drawParameter, data); drawTimer.Stop(); double drawTime = drawTimer.GetMilliseconds(); stats.drawMinTime = std::min(stats.drawMinTime, drawTime); stats.drawMaxTime = std::max(stats.drawMaxTime, drawTime); stats.drawTotalTime += drawTime; } current++; } statistics.push_back(stats); } #if defined(HAVE_LIB_GPERFTOOLS) if (args.heapProfile){ HeapProfilerStop(); } #endif std::cout << "==========" << std::endl; for (const auto& stats : statistics) { std::cout << "Level: " << stats.level << std::endl; std::cout << "Tiles: " << stats.tileCount << " (load " << args.loadRepeat << "x, drawn " << args.drawRepeat << "x)" << std::endl; #if defined(HAVE_MALLINFO) || defined(HAVE_LIB_GPERFTOOLS) std::cout << " Used memory: "; std::cout << "max: " << formatAlloc(stats.allocMax) << " "; std::cout << "avg: " << formatAlloc(stats.allocSum / (stats.tileCount * args.loadRepeat)) << std::endl; #endif std::cout << " Tot. data : "; std::cout << "nodes: " << stats.nodeCount << " "; std::cout << "way: " << stats.wayCount << " "; std::cout << "areas: " << stats.areaCount << std::endl; if (stats.tileCount>0) { std::cout << " Avg. data : "; std::cout << "nodes: " << stats.nodeCount/stats.tileCount << " "; std::cout << "way: " << stats.wayCount/stats.tileCount << " "; std::cout << "areas: " << stats.areaCount/stats.tileCount << std::endl; } std::cout << " DB : "; std::cout << "total: " << stats.dbTotalTime << " "; std::cout << "min: " << stats.dbMinTime << " "; if (stats.tileCount>0) { std::cout << "avg: " << stats.dbTotalTime/(stats.tileCount * args.loadRepeat) << " "; } std::cout << "max: " << stats.dbMaxTime << " " << std::endl; std::cout << " Map : "; std::cout << "total: " << stats.drawTotalTime << " "; std::cout << "min: " << stats.drawMinTime << " "; if (stats.tileCount>0) { std::cout << "avg: " << stats.drawTotalTime/(stats.tileCount * args.drawRepeat) << " "; } std::cout << "max: " << stats.drawMaxTime << std::endl; } database->Close(); return 0; }