bool IsSameEnough(const Tile& lhs, const Tile& rhs) { for (const auto& num : kAllEdgeNumber) { if (!IsSameEnough(lhs.GetEdge(num), rhs.GetEdge(num))) { return false; } } return true; }
bool TileCollection::IsOverlapCursor(const Tile& cursor) const { for (const auto& edge : outline_edges_) { for (const auto& num : kAllEdgeNumber) { const auto cursor_edge = cursor.GetEdge(num); if (IsIntersectLineSegment(cursor_edge.Begin(), cursor_edge.End(), edge.Begin(), edge.End())) { return true; } } } return false; }
MaybeEdges TileCollection::TryOutlineEdges(const Tile& tile, bool is_add) const { using std::begin; using std::end; using EdgeList = std::list<Edge>; using EdgeListIter = EdgeList::iterator; EdgeList edge_list(begin(outline_edges_), end(outline_edges_)); const auto get_overlap_iter = [&edge_list](const Edge& edge) { return std::find_if(begin(edge_list), end(edge_list), [&edge](const Edge& candidate) { return IsSameEnough(candidate, edge); }); }; std::vector<EdgeListIter> to_be_removed; EdgeNum start_add_num = kEdge3, end_add_num = kEdge3; int num_of_interchange = 0; bool is_previous_overlap = get_overlap_iter(tile.GetEdge(kEdge3)) != end(edge_list); for (const auto& num : kAllEdgeNumber) { const auto it = get_overlap_iter(tile.GetEdge(num)); const bool is_current_overlap = it != end(edge_list); if (is_current_overlap) { to_be_removed.push_back(it); } if (is_previous_overlap != is_current_overlap) { ++num_of_interchange; if (is_current_overlap) { if (is_add) { start_add_num += num; } else { // is_remove end_add_num = num; } } else { // is_previous_overlap == true if (is_add) { end_add_num += num; } else { // is_remove start_add_num = num; } } } is_previous_overlap = is_current_overlap; } if (to_be_removed.empty()) { if (is_add) { Q_UNREACHABLE(); } else { // is_remove return boost::none; } } Q_ASSERT(num_of_interchange % 2 == 0); if (num_of_interchange != 2) { return boost::none; } auto insert_point = begin(edge_list); for (const auto removed : to_be_removed) { insert_point = edge_list.erase(removed); } if (is_add) { for (EdgeNum num = start_add_num; num != end_add_num; --num) { insert_point = edge_list.insert(insert_point, tile.GetEdge(num)); } } else { // is_remove for (EdgeNum num = start_add_num; num != end_add_num; ++num) { if (const auto internal = GetCorrespondingEdge(tile.GetEdge(num))) { insert_point = edge_list.insert(insert_point, *internal); } else { Q_UNREACHABLE(); } } } return Edges{begin(edge_list), end(edge_list)}; }