adds map_pos to a group if an adjacent one exists, or creates one if none exist... if multiple exist they're merged into the first found
| 75 | |
| 76 | // adds map_pos to a group if an adjacent one exists, or creates one if none exist... if multiple exist they're merged into the first found |
| 77 | void ChannelGroups::add(const df::coord &map_pos) { |
| 78 | // if we've already added this, we don't need to do it again |
| 79 | if (groups_map.count(map_pos)) { |
| 80 | return; |
| 81 | } |
| 82 | /* We need to add map_pos to an existing group if possible... |
| 83 | * So what we do is we look at neighbours to see if they belong to one or more existing groups |
| 84 | * If there is more than one group, we'll be merging them |
| 85 | */ |
| 86 | df::coord neighbors[8]; |
| 87 | get_neighbours(map_pos, neighbors); |
| 88 | Group* group = nullptr; |
| 89 | int group_index = -1; |
| 90 | |
| 91 | DEBUG(groups).print(" add(" COORD ")\n", COORDARGS(map_pos)); |
| 92 | // and so we begin iterating the neighbours |
| 93 | for (auto &neighbour: neighbors) { |
| 94 | if unlikely(!Maps::isValidTilePos(neighbour)) continue; |
| 95 | // go to the next neighbour if this one doesn't have a group |
| 96 | if (!groups_map.count(neighbour)) { |
| 97 | TRACE(groups).print(" -> neighbour is not designated\n"); |
| 98 | continue; |
| 99 | } |
| 100 | // get the group, since at least one exists... then merge any additional into that one |
| 101 | if (!group){ |
| 102 | TRACE(groups).print(" -> group* has no valid state yet\n"); |
| 103 | group_index = groups_map.find(neighbour)->second; |
| 104 | group = &groups.at(group_index); |
| 105 | } else { |
| 106 | TRACE(groups).print(" -> group* has an existing state\n"); |
| 107 | |
| 108 | // we don't do anything if the found group is the same as the existing group |
| 109 | auto index2 = groups_map.find(neighbour)->second; |
| 110 | if (group_index != index2) { |
| 111 | // we already have group "prime" if you will, so we're going to merge the new find into prime |
| 112 | Group &group2 = groups.at(index2); |
| 113 | // merge |
| 114 | TRACE(groups).print(" -> merging two groups. group 1 size: {}. group 2 size: {}\n", group->size(), |
| 115 | group2.size()); |
| 116 | for (auto pos2: group2) { |
| 117 | group->emplace(pos2); |
| 118 | groups_map[pos2] = group_index; |
| 119 | } |
| 120 | group2.clear(); |
| 121 | free_spots.emplace(index2); |
| 122 | TRACE(groups).print(" merged size: {}\n", group->size()); |
| 123 | } |
| 124 | } |
| 125 | } |
| 126 | // if we haven't found at least one group by now we need to create/get one |
| 127 | if (!group) { |
| 128 | TRACE(groups).print(" -> no merging took place\n"); |
| 129 | // first we check if we can re-use a group that's been freed |
| 130 | if (!free_spots.empty()) { |
| 131 | TRACE(groups).print(" -> use recycled old group\n"); |
| 132 | // first element in a set is always the lowest value, so we re-use from the front of the vector |
| 133 | group_index = *free_spots.begin(); |
| 134 | group = &groups[group_index]; |
nothing calls this directly
no test coverage detected