Map3 foo( Map1 const & m1, Map2 const & m2 ) { auto m2end = m2.end(); // a constant call is move outside the loop Map3 result; for( auto & v1 : m1 ) { // each entry in m1 is made of the key as first and the value as second for( auto & p1 : v1.second ) { // iterate over the vector of pair auto v2it = m2.find( p1 ); // search for the pair if ( v2it != m2end ) { result[v1.first] += v2it->second; // if the pair was found, add the value for it to the result, using the map1 key as key } } } return result; }
void BBFind::squash(Map2 &map, float scaleMin, float scaleMax) { // Overloaded to work on Map2 or Map3. Normalizes, but sets // initial min / max values to given arguments. If the given // range is larger than the data's range, the data is scaled // down proportionally. Otherwise, it just normalizes to the // given range. int mapWidth = (int)map[0].size(); int mapHeight = (int)map.size(); float maxVal = scaleMax; float minVal = scaleMin; for(int x = 0; x < mapWidth; x++) { for(int y = 0; y < mapHeight; y++) { float val = map[y][x]; maxVal = val > maxVal ? val : maxVal; minVal = val < minVal ? val : minVal; } } float range = maxVal - minVal; #ifdef PV_USE_OPENMP_THREADS #pragma omp parallel for #endif for(int x = 0; x < mapWidth; x++) { for(int y = 0; y < mapHeight; y++) { map[y][x] = scaleMin + ((map[y][x] - minVal) / range) * scaleMax; } } }
float BBFind::sigmoidedRMS(const Map2 confMap, const Rectangle &bounds) { // Takes the RMS of the given sub area and applies a sigmoid to // smoothly cap values at 1.0 int mapWidth = confMap[0].size(); int mapHeight = confMap.size(); float sum = 0.0f; for(int x = 0; x < bounds.width; x++) { for(int y = 0; y < bounds.height; y++) { int _x = bounds.left() + x; int _y = bounds.top() + y; if(_x < 0 || _x >= mapWidth || _y < 0 || _y >= mapHeight) continue; sum += pow(confMap[_y][_x], 2); } } float avg = sqrt(sum / (mapWidth*mapHeight)); float e = exp(1); // This is a very easy curve that still soft caps at 1.0. // Combined with the increaseContrast function, it allows // values > 0.85 to bring the average up based on the contrast argument. return (1.0f / (1.0f + pow(e,-e*avg)) - 0.5f) * 2.0f; }
BBFind::Map2 BBFind::scale(const Map2 &source, int newWidth, int newHeight, bool bilinear) { // Rescales the map's dimensions using either // bilinear interpolation or nearest neighbor. Map2 result(newHeight); int sourceWidth = source[0].size(); int sourceHeight = source.size(); if(bilinear) // Bilinear scaling { for(int j = 0; j < newHeight; j++) { result[j].resize(newWidth); for(int i = 0; i < newWidth; i++) { float xSource = i / (float)(newWidth-1) * (sourceWidth-1); float ySource = j / (float)(newHeight-1) * (sourceHeight-1); int leftIndex = (int)xSource; int rightIndex = (int)ceil(xSource); int topIndex = (int)ySource; int bottomIndex = (int)ceil(ySource); if(topIndex < 0) topIndex = 0; if(leftIndex < 0) leftIndex = 0; if(rightIndex >= sourceWidth) rightIndex = sourceWidth-1; if(bottomIndex >= sourceHeight) bottomIndex = sourceHeight-1; float xAlign = xSource - leftIndex; float yAlign = ySource - topIndex; float tl = source[topIndex][leftIndex] * (1.0f - xAlign) * (1.0f - yAlign); float tr = source[topIndex][rightIndex] * xAlign * (1.0f - yAlign); float bl = source[bottomIndex][leftIndex] * (1.0f - xAlign) * yAlign; float br = source[bottomIndex][rightIndex] * xAlign * yAlign; result[j][i] = tl+tr+bl+br; } } } else // Nearest neighbor scaling, no interpolation { float xRatio = sourceWidth / (float)(newWidth); float yRatio = sourceHeight / (float)(newHeight); #ifdef PV_USE_OPENMP_THREADS #pragma omp parallel for #endif for(int j = 0; j < newHeight; j++) { result[j].resize(newWidth); for(int i = 0; i < newWidth; i++) { result[j][i] = source[(int)(j*yRatio)][(int)(i*xRatio)]; } } } return result; }
static void BENCH_Dart_count_single_threaded(benchmark::State& state) { while (state.KeepRunning()) { unsigned nb_darts = 0u; bench_map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); } }
static void BENCH_Dart_count_multi_threaded(benchmark::State& state) { while (state.KeepRunning()) { uint32 nb_darts_2 = 0u; std::vector<uint32> nb_darts_per_thread(cgogn::nb_threads() + 2); for (auto& n : nb_darts_per_thread) n = 0u; nb_darts_2 = 0u; bench_map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, uint32 thread_index) { nb_darts_per_thread[thread_index]++; }); for (uint32 n : nb_darts_per_thread) nb_darts_2 += n; cgogn_assert(nb_darts_2 == bench_map.nb_darts()); } }
void Viewer::import(const std::string& surfaceMesh) { cgogn::io::import_surface<Vec3>(map_, surfaceMesh); map_.get_attribute(vertex_position_, "position"); cgogn::geometry::compute_AABB(vertex_position_, bb_); setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); showEntireScene(); }
BBFind::Map2 BBFind::applyThreshold(const Map2 confMap, float threshold) { // Clips any values below threshold // TODO: Can this just modify the map in-place? int mapWidth = confMap[0].size(); int mapHeight = confMap.size(); Map2 resultMap = confMap; #ifdef PV_USE_OPENMP_THREADS #pragma omp parallel for #endif for(int x = 0; x < mapWidth; x++) { for(int y = 0; y < mapHeight; y++) { resultMap[y][x] = (confMap[y][x] >= threshold ? confMap[y][x] : 0.0f); } } return resultMap; }
static void BENCH_vertices_normals_cache_multi_threaded(benchmark::State& state) { while(state.KeepRunning()) { state.PauseTiming(); VertexAttribute<Vec3> vertex_position = bench_map.get_attribute<Vec3, VERTEX>("position"); cgogn_assert(vertex_position.is_valid()); VertexAttribute<Vec3> vertices_normal = bench_map.get_attribute<Vec3, VERTEX>("normal"); cgogn_assert(vertices_normal.is_valid()); cgogn::CellCache<Map2> cache(bench_map); cache.template build<Vertex>(); state.ResumeTiming(); bench_map.parallel_foreach_cell([&] (Vertex v, uint32) { vertices_normal[v] = cgogn::geometry::normal<Vec3>(bench_map, v, vertex_position); }, cache); } }
static void BENCH_faces_normals_cache_single_threaded(benchmark::State& state) { while(state.KeepRunning()) { state.PauseTiming(); VertexAttribute<Vec3> vertex_position = bench_map.get_attribute<Vec3, VERTEX>("position"); cgogn_assert(vertex_position.is_valid()); FaceAttribute<Vec3> face_normal = bench_map.get_attribute<Vec3, FACE>("normal"); cgogn_assert(face_normal.is_valid()); cgogn::CellCache<Map2> cache(bench_map); cache.template build<Face>(); state.ResumeTiming(); bench_map.foreach_cell([&] (Face f) { face_normal[f] = cgogn::geometry::normal<Vec3>(bench_map, f, vertex_position); }, cache); } }
int main(int , char** ) { int32 x = 4; int32 y = 4; const cgogn::Orbit vertorb = Map2::Vertex::ORBIT; { Map2 map; VertexAttribute<Vec3> vertex_grid = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("grid"); VertexAttribute<Vec3> vertex_twisted_strip = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("twisted_strip"); VertexAttribute<Vec3> vertex_helicoid = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("helicoid"); // map.add_attribute<int32, Map2::CDart::ORBIT>("darts"); map.add_attribute<int32, Map2::Edge::ORBIT>("edges"); map.add_attribute<int32, Map2::Face::ORBIT>("faces"); map.add_attribute<int32, Map2::Volume::ORBIT>("volumes"); cgogn::modeling::SquareGrid<Map2> g(map, x, y); std::cout << "is good ? " << std::boolalpha << map.check_embedding_integrity() << std::endl; g.embed_into_grid(vertex_grid, 10.0f, 10.0f, 0.0f); g.embed_into_twisted_strip<Vec3>(vertex_twisted_strip, 10.0f, 5.0f, 3.1f); g.embed_into_helicoid<Vec3>(vertex_helicoid, 10.0f, 5.0f, 15.0f, 3.0f, 1); cgogn::io::export_surface(map, cgogn::io::ExportOptions("grid.off", {vertorb, "grid"}, {}, false, false)); cgogn::io::export_surface(map, cgogn::io::ExportOptions("twisted_strip.off", {vertorb, "twisted_strip"}, {}, false, false)); cgogn::io::export_surface(map, cgogn::io::ExportOptions("helicoid.off", {vertorb, "helicoid"}, {}, false, false)); } { Map2 map; VertexAttribute<Vec3> vertex_cylinder = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("cylinder"); VertexAttribute<Vec3> vertex_sphere = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("sphere"); VertexAttribute<Vec3> vertex_cone = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("cone"); // map.add_attribute<int32, Map2::CDart::ORBIT>("darts"); map.add_attribute<int32, Map2::Edge::ORBIT>("edges"); map.add_attribute<int32, Map2::Face::ORBIT>("faces"); map.add_attribute<int32, Map2::Volume::ORBIT>("volumes"); cgogn::modeling::SquareCylinder<Map2> g(map, x, y); std::cout << "is good ? " << std::boolalpha << map.check_embedding_integrity() << std::endl; g.close_top(); g.close_bottom(); g.triangule_top(); g.triangule_bottom(); g.embed_into_cylinder(vertex_cylinder, 10.0f, 8.0f, 5.0f); g.embed_into_sphere<Vec3>(vertex_sphere, 10.0f); g.embed_into_cone<Vec3>(vertex_cone, 10.0f, 5.0f); cgogn::io::export_surface(map, cgogn::io::ExportOptions("cylinder.off", {vertorb, "cylinder"}, {}, false, false)); cgogn::io::export_surface(map, cgogn::io::ExportOptions("sphere.off", {vertorb, "sphere"}, {}, false, false)); cgogn::io::export_surface(map, cgogn::io::ExportOptions("cone.off", {vertorb, "cone"}, {}, false, false)); } { Map2 map; VertexAttribute<Vec3> vertex_tore = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("tore"); // map.add_attribute<int32, Map2::CDart::ORBIT>("darts"); map.add_attribute<int32, Map2::Edge::ORBIT>("edges"); map.add_attribute<int32, Map2::Face::ORBIT>("faces"); map.add_attribute<int32, Map2::Volume::ORBIT>("volumes"); cgogn::modeling::SquareTore<Map2> g(map, x, y); std::cout << "is good ? " << std::boolalpha << map.check_embedding_integrity() << std::endl; g.embed_into_tore(vertex_tore, 10.0f, 4.0f); cgogn::io::export_surface(map, cgogn::io::ExportOptions("tore.off", {vertorb, "tore"}, {}, false, false)); } /* { Map2 map; cgogn::modeling::TriangularCube<Map2> g(map, x, y, x); VertexAttribute<Vec3> vertex_tore = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("cube"); g.embed_into_cube(vertex_tore, 10.0f, 4.0f, 5.0f); std::vector<std::pair<cgogn::Orbit,std::string>> att_vec; att_vec.push_back(std::make_pair(cgogn::Orbit(Map2::Vertex::ORBIT), std::string("cube"))); cgogn::io::export_surface(map, cgogn::io::ExportOptions("cube.off", att_vec, false)); } */ return 0; }
BBFind::Map2 BBFind::makeEdgeDistanceMap(const Map2 confMap) { // Modified Dijkstra map algorithm based on: // http://www.roguebasin.com/index.php?title=The_Incredible_Power_of_Dijkstra_Maps // The original algorithm finds nearest distance to a goal. // This modified version finds the larger distance, horizontal or vertical, // to a 0 confidence value (used to find object edges after threshold clipping) int mapWidth = confMap[0].size(); int mapHeight = confMap.size(); int maxVal = std::max(mapWidth, mapHeight); Map2 horizMap(mapHeight); Map2 vertMap(mapHeight); for(int y = 0; y < mapHeight; y++) { horizMap[y].resize(mapWidth); vertMap[y].resize(mapWidth); for(int x = 0; x < mapWidth; x++) { if(confMap[y][x] > 0) { horizMap[y][x] = maxVal; vertMap[y][x] = maxVal; } } } // Finds the shortest distance to 0 conf value in horizontal and vertical direction, // and stores the biggest one into result. This allows long, thin confidence chunks // to avoid clipping bool changed = true; while(changed) { changed = false; for(int y = 1; y < mapHeight-1; y++) { for(int x = 1; x < mapWidth-1; x++) { float lowest = horizMap[y][x]; lowest = std::min(lowest, horizMap[y][x-1]); lowest = std::min(lowest, horizMap[y][x+1]); if(horizMap[y][x] > lowest+1) { horizMap[y][x] = lowest + 1; changed = true; } } } } changed = true; while(changed) { changed = false; for(int y = 1; y < mapHeight-1; y++) { for(int x = 1; x < mapWidth-1; x++) { float lowest = vertMap[y][x]; lowest = std::min(lowest, vertMap[y-1][x]); lowest = std::min(lowest, vertMap[y+1][x]); if(vertMap[y][x] > lowest+1) { vertMap[y][x] = lowest + 1; changed = true; } } } } Map2 resultMap = horizMap; #ifdef PV_USE_OPENMP_THREADS #pragma omp parallel for #endif for(int y = 0; y < mapHeight; y++) { for(int x = 0; x < mapWidth; x++) { if(vertMap[y][x] > resultMap[y][x]) { resultMap[y][x] = vertMap[y][x]; } } } return resultMap; }
int main(int argc, char** argv) { std::string surfaceMesh; if (argc < 2) { cgogn_log_info("cmap2_import") << "USAGE: " << argv[0] << " [filename]"; surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); cgogn_log_info("cmap2_import") << "Using default mesh : " << surfaceMesh; } else surfaceMesh = std::string(argv[1]); Map2 map; for (uint32 k = 0; k < 2; ++k) { cgogn::io::import_surface<Vec3>(map, surfaceMesh); uint32 nb_darts = 0; map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); cgogn_log_info("cmap2_import") << "nb darts -> " << nb_darts; uint32 nb_darts_2 = 0; std::vector<uint32> nb_darts_per_thread(cgogn::NB_THREADS - 1); for (uint32& n : nb_darts_per_thread) n = 0; map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, uint32 thread_index) { nb_darts_per_thread[thread_index]++; }); for (uint32 n : nb_darts_per_thread) nb_darts_2 += n; cgogn_log_info("cmap2_import")<< "nb darts // -> " << nb_darts_2; VertexAttribute<Vec3> vertex_position = map.get_attribute<Vec3, Map2::Vertex::ORBIT>("position"); VertexAttribute<Vec3> vertex_normal = map.add_attribute<Vec3, Map2::Vertex::ORBIT>("normal"); FaceAttribute<Vec3> face_normal = map.add_attribute<Vec3, Map2::Face::ORBIT>("normal"); cgogn_log_info("cmap2_import") << "Map integrity : " << std::boolalpha << map.check_map_integrity(); uint32 nb_vertices = 0; cgogn::CellCache<Map2> cache(map); cache.build<Map2::Vertex>(); map.foreach_cell([&nb_vertices] (Map2::Vertex) { nb_vertices++; }, cache); cgogn_log_info("cmap2_import") << "nb vertices -> " << nb_vertices; uint32 nb_boundary_faces = 0; cgogn::BoundaryCache<Map2> bcache(map); map.foreach_cell([&nb_boundary_faces] (Map2::Boundary) { nb_boundary_faces++; }, bcache); cgogn_log_info("cmap2_import") << "nb boundary faces -> " << nb_boundary_faces; uint32 nb_faces = 0; map.foreach_cell([&nb_faces] (Map2::Face) { nb_faces++;}); cgogn_log_info("cmap2_import") << "nb faces -> " << nb_faces; uint32 nb_faces_2 = 0; std::vector<uint32> nb_faces_per_thread(cgogn::NB_THREADS - 1); for (uint32& n : nb_faces_per_thread) n = 0; map.parallel_foreach_cell([&nb_faces_per_thread] (Map2::Face, uint32 thread_index) { nb_faces_per_thread[thread_index]++; }); for (uint32 n : nb_faces_per_thread) nb_faces_2 += n; cgogn_log_info("cmap2_import") << "nb faces // -> " << nb_faces_2; std::chrono::time_point<std::chrono::system_clock> start, end; start = std::chrono::system_clock::now(); for (uint32 i = 0; i < 10; ++i) cgogn::geometry::compute_normal<Vec3>(map, vertex_position, face_normal); for (uint32 i = 0; i < 10; ++i) cgogn::geometry::compute_normal<Vec3>(map, vertex_position, vertex_normal); end = std::chrono::system_clock::now(); std::chrono::duration<float64> elapsed_seconds = end - start; cgogn_log_info("cmap2_import") << "elapsed time: " << elapsed_seconds.count() << "s"; } return 0; }
// ========================================================================== /// Main execution // ========================================================================== StatusCode MapAlg::execute() { using namespace Gaudi::Utils ; Rndm::Numbers gauss ( randSvc() , Rndm::Gauss ( 0.0 , 1.0 ) ) ; Rndm::Numbers gauss2 ( randSvc() , Rndm::Gauss ( 0.0 , 10.0 ) ) ; const Key key = Key ( gauss2 () ) ; const Value value1 = Value( int( 100 * gauss () ) ) / 100.0 ; always() << " Inserting key " << toString(key) << " 1st: " << " " << toString ( m_map1.insert ( std::make_pair ( key , value1 ) ).second ) << " " << toString ( m_map2.insert ( std::make_pair ( key , value1 ) ).second ) << " " << toString ( m_map3.insert ( std::make_pair ( key , value1 ) ).second ) << " " << toString ( m_map4.insert ( std::make_pair ( key , value1 ) ).second ) << endmsg ; always() << "1 Map1: " << toString ( m_map1 ) << endmsg ; always() << "1 Map2: " << toString ( m_map2 ) << endmsg ; always() << "1 Map3: " << toString ( m_map3 ) << endmsg ; always() << "1 Map4: " << toString ( m_map4 ) << endmsg ; print1 ( (Key) 1 ) ; always() << "2 Map1: " << toString ( m_map1 ) << endmsg ; always() << "2 Map2: " << toString ( m_map2 ) << endmsg ; always() << "2 Map3: " << toString ( m_map3 ) << endmsg ; always() << "2 Map4: " << toString ( m_map4 ) << endmsg ; print2 ( (Key) 7 ) ; always() << "3 Map1: " << toString ( m_map1 ) << endmsg ; always() << "3 Map2: " << toString ( m_map2 ) << endmsg ; always() << "3 Map3: " << toString ( m_map3 ) << endmsg ; always() << "3 Map4: " << toString ( m_map4 ) << endmsg ; const Value value2 = gauss () ; always() << " Inserting key " << toString(key) << " 2nd: " << " " << toString ( m_map1.insert ( std::make_pair ( key , value2 ) ).second ) << " " << toString ( m_map2.insert ( std::make_pair ( key , value2 ) ).second ) << " " << toString ( m_map3.insert ( std::make_pair ( key , value2 ) ).second ) << " " << toString ( m_map4.insert ( std::make_pair ( key , value2 ) ).second ) << endmsg ; always() << "4 Map1: " << toString ( m_map1 ) << endmsg ; always() << "4 Map2: " << toString ( m_map2 ) << endmsg ; always() << "4 Map3: " << toString ( m_map3 ) << endmsg ; always() << "4 Map4: " << toString ( m_map4 ) << endmsg ; if ( 0 == ::labs(key)%2 ) { always() << " Erased : " << " " << toString ( 0 != m_map1.erase ( key ) ) << " " << toString ( 0 != m_map2.erase ( key ) ) << " " << toString ( 0 != m_map3.erase ( key ) ) << " " << toString ( 0 != m_map4.erase ( key ) ) << endmsg ; } always() << "5 Map1: " << toString ( m_map1 ) << endmsg ; always() << "5 Map2: " << toString ( m_map2 ) << endmsg ; always() << "5 Map3: " << toString ( m_map3 ) << endmsg ; always() << "5 Map4: " << toString ( m_map4 ) << endmsg ; always() << " Count key 0 : " << " " << m_map1.count ( 0 ) << " " << m_map2.count ( 0 ) << " " << m_map3.count ( 0 ) << " " << m_map4.count ( 0 ) << endmsg ; always() << " Count key 1 : " << " " << m_map1.count ( 1 ) << " " << m_map2.count ( 1 ) << " " << m_map3.count ( 1 ) << " " << m_map4.count ( 1 ) << endmsg ; always() << " Count key 7 : " << " " << m_map1.count ( 7 ) << " " << m_map2.count ( 7 ) << " " << m_map3.count ( 7 ) << " " << m_map4.count ( 7 ) << endmsg ; always() << " Count key -100 : " << " " << m_map1.count ( -100 ) << " " << m_map2.count ( -100 ) << " " << m_map3.count ( -100 ) << " " << m_map4.count ( -100 ) << endmsg ; return StatusCode::SUCCESS; }
void intersectValues(Map const& map, Map2 const& map2, DotProductResult& dotResult) { if (map.size() < map2.size()) intersectValues(map.begin(), map.end(), map2, dotResult); else intersectValues(map, map2.begin(), map2.end(), dotResult); }