Intersection WorldViewer::pixelIntersect(const int2 &screen_pos, const FindFilter &filter) const { Intersection out; FBox out_bbox; if(filter.flags() & Flags::tile) { const TileMap &tile_map = m_world->tileMap(); vector<int> inds; tile_map.findAll(inds, IRect(screen_pos, screen_pos + int2(1, 1)), filter.flags() | Flags::visible); for(int i = 0; i < (int)inds.size(); i++) { const auto &desc = tile_map[inds[i]]; FBox bbox = desc.bbox; if(out.empty() || drawingOrder(bbox, out_bbox) == 1) if(desc.ptr->testPixel(screen_pos - worldToScreen((int3)bbox.min))) { out = ObjectRef(inds[i], false); out_bbox = bbox; } } } if(filter.flags() & Flags::entity) { int ignore_index = m_world->filterIgnoreIndex(filter); for(int n = 0; n < (int)m_entities.size(); n++) { const Entity *entity = refEntity(n); if(!entity || !m_occluder_config.isVisible(m_entities[n].occluder_id) || !Flags::test(entity->flags(), filter.flags()) || n == ignore_index) continue; if(!entity->testPixel(screen_pos)) continue; FBox bbox = entity->boundingBox(); //TODO: check this if(out.empty() || drawingOrder(bbox, out_bbox) == 1) { out = ObjectRef(n, true); out_bbox = bbox; } } } if(out.empty()) return Intersection(); return Intersection(out, intersection(screenRay(screen_pos), out_bbox)); }
std::pair<util::guidance::EntryClass, util::guidance::BearingClass> classifyIntersection(Intersection intersection) { if (intersection.empty()) return {}; std::sort(intersection.begin(), intersection.end(), [](const ConnectedRoad &left, const ConnectedRoad &right) { return left.bearing < right.bearing; }); util::guidance::EntryClass entry_class; util::guidance::BearingClass bearing_class; const bool canBeDiscretized = [&]() { if (intersection.size() <= 1) return true; DiscreteBearing last_discrete_bearing = util::guidance::BearingClass::getDiscreteBearing( std::round(intersection.back().bearing)); for (const auto road : intersection) { const DiscreteBearing discrete_bearing = util::guidance::BearingClass::getDiscreteBearing(std::round(road.bearing)); if (discrete_bearing == last_discrete_bearing) return false; last_discrete_bearing = discrete_bearing; } return true; }(); // finally transfer data to the entry/bearing classes std::size_t number = 0; if (canBeDiscretized) { if (util::guidance::BearingClass::getDiscreteBearing(intersection.back().bearing) < util::guidance::BearingClass::getDiscreteBearing(intersection.front().bearing)) { intersection.insert(intersection.begin(), intersection.back()); intersection.pop_back(); } for (const auto &road : intersection) { if (road.entry_allowed) entry_class.activate(number); auto discrete_bearing_class = util::guidance::BearingClass::getDiscreteBearing(std::round(road.bearing)); bearing_class.add(std::round(discrete_bearing_class * util::guidance::BearingClass::discrete_step_size)); ++number; } } else { for (const auto &road : intersection) { if (road.entry_allowed) entry_class.activate(number); bearing_class.add(std::round(road.bearing)); ++number; } } return std::make_pair(entry_class, bearing_class); }