//! Place labels with greedy algorithm void Renderer::placeLabels(const std::list<shared_ptr<Label> >& labels, std::vector<shared_ptr<Label> >& placed) { std::vector<shared_ptr<Label>> contained; contained.reserve(labels.size()); // first sort out all out-of-bounds labels for (auto& l : labels) { if (bounds.contains(l->box)) contained.push_back(l); else if (bounds.getIntersection(l->box).getArea() > 0.0){ if (isCutOff(l->box, l->owner)) continue; double intersect_max = 0.0; for (auto& other : placed) intersect_max = std::max(intersect_max, other->box.getIntersection(l->box).getArea()); if (intersect_max < RENDERER_LABEL_OVERLAP * l->box.getArea()) placed.push_back(l); } } for (auto& l : contained) { double width = l->box.getWidth(); double height = l->box.getHeight(); FloatPoint trans[5] = { FloatPoint(0.0, 0.0), // original FloatPoint(0.0, -height/2.0), // above FloatPoint(width/2.0, 0.0), // to the right FloatPoint(0.0, height/2.0), // below FloatPoint(width/2.0, 0.0) // to the left }; FloatRect possible[5]; for (int i = 0; i < 5; i++) possible[i] = l->box.translate(trans[i].x, trans[i].y); // stores the size of the intersecting area double intersect_max[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; for (auto& other : placed) { for (int i = 0; i < 5; i++) { FloatRect intersection = possible[i].getIntersection(other->box); intersect_max[i] = std::max(intersect_max[i], intersection.getArea()); } } int min = 0; for (int i = 1; i < 5; i++) if (intersect_max[i] < intersect_max[min] && bounds.contains(possible[i])) // don't push label outside of the bounding-box min = i; // only place label if intersecting area is 1/10 the label if (intersect_max[min] < RENDERER_LABEL_OVERLAP * l->box.getArea()) { l->translate(trans[min].x, trans[min].y); placed.push_back(l); } } }
//! Place labels with greedy algorithm void Renderer::placeShields(const std::list<shared_ptr<Shield> >& shields, std::vector<shared_ptr<Shield> >& placed) { std::vector<shared_ptr<Shield>> contained; contained.reserve(10); // first sort out all out-of-bounds labels for (auto& shield : shields) { if (!bounds.contains(shield->shield)) continue; // stores the size of the intersecting area double intersect_max = 0.0; for (auto& other : placed) { FloatRect intersection = shield->box.getIntersection(other->box); intersect_max = std::max(intersect_max, intersection.getArea()); } // only place label if intersecting area is 1/10 the label if (intersect_max < RENDERER_SHIELD_OVERLAP * shield->box.getArea()) placed.push_back(shield); } }