// Attempt to improve this by adding partitions or expanding partitions. void ColPartitionSet::ImproveColumnCandidate(WidthCallback* cb, PartSetVector* src_sets) { int set_size = src_sets->size(); // Iterate over the provided column sets, as each one may have something // to improve this. for (int i = 0; i < set_size; ++i) { ColPartitionSet* column_set = src_sets->get(i); if (column_set == NULL) continue; // Iterate over the parts in this and column_set, adding bigger or // new parts in column_set to this. ColPartition_IT part_it(&parts_); ASSERT_HOST(!part_it.empty()); int prev_right = MIN_INT32; part_it.mark_cycle_pt(); ColPartition_IT col_it(&column_set->parts_); for (col_it.mark_cycle_pt(); !col_it.cycled_list(); col_it.forward()) { ColPartition* col_part = col_it.data(); if (col_part->blob_type() < BRT_UNKNOWN) continue; // Ignore image partitions. int col_left = col_part->left_key(); int col_right = col_part->right_key(); // Sync-up part_it (in this) so it matches the col_part in column_set. ColPartition* part = part_it.data(); while (!part_it.at_last() && part->right_key() < col_left) { prev_right = part->right_key(); part_it.forward(); part = part_it.data(); } int part_left = part->left_key(); int part_right = part->right_key(); if (part_right < col_left || col_right < part_left) { // There is no overlap so this is a new partition. AddPartition(col_part->ShallowCopy(), &part_it); continue; } // Check the edges of col_part to see if they can improve part. bool part_width_ok = cb->Run(part->KeyWidth(part_left, part_right)); if (col_left < part_left && col_left > prev_right) { // The left edge of the column is better and it doesn't overlap, // so we can potentially expand it. int col_box_left = col_part->BoxLeftKey(); bool tab_width_ok = cb->Run(part->KeyWidth(col_left, part_right)); bool box_width_ok = cb->Run(part->KeyWidth(col_box_left, part_right)); if (tab_width_ok || (!part_width_ok )) { // The tab is leaving the good column metric at least as good as // it was before, so use the tab. part->CopyLeftTab(*col_part, false); part->SetColumnGoodness(cb); } else if (col_box_left < part_left && (box_width_ok || !part_width_ok)) { // The box is leaving the good column metric at least as good as // it was before, so use the box. part->CopyLeftTab(*col_part, true); part->SetColumnGoodness(cb); } part_left = part->left_key(); } if (col_right > part_right && (part_it.at_last() || part_it.data_relative(1)->left_key() > col_right)) { // The right edge is better, so we can possibly expand it. int col_box_right = col_part->BoxRightKey(); bool tab_width_ok = cb->Run(part->KeyWidth(part_left, col_right)); bool box_width_ok = cb->Run(part->KeyWidth(part_left, col_box_right)); if (tab_width_ok || (!part_width_ok )) { // The tab is leaving the good column metric at least as good as // it was before, so use the tab. part->CopyRightTab(*col_part, false); part->SetColumnGoodness(cb); } else if (col_box_right > part_right && (box_width_ok || !part_width_ok)) { // The box is leaving the good column metric at least as good as // it was before, so use the box. part->CopyRightTab(*col_part, true); part->SetColumnGoodness(cb); } } } } ComputeCoverage(); }
// The column_set has changed. Close down all in-progress WorkingPartSets in // columns that do not match and start new ones for the new columns in this. // As ColPartitions are turned into BLOCKs, the used ones are put in // used_parts, as they still need to be referenced in the grid. void ColPartitionSet::ChangeWorkColumns(const ICOORD& bleft, const ICOORD& tright, int resolution, ColPartition_LIST* used_parts, WorkingPartSet_LIST* working_set_list) { // Move the input list to a temporary location so we can delete its elements // as we add them to the output working_set. WorkingPartSet_LIST work_src; WorkingPartSet_IT src_it(&work_src); src_it.add_list_after(working_set_list); src_it.move_to_first(); WorkingPartSet_IT dest_it(working_set_list); // Completed blocks and to_blocks are accumulated and given to the first new // one whenever we keep a column, or at the end. BLOCK_LIST completed_blocks; TO_BLOCK_LIST to_blocks; WorkingPartSet* first_new_set = NULL; WorkingPartSet* working_set = NULL; ColPartition_IT col_it(&parts_); for (col_it.mark_cycle_pt(); !col_it.cycled_list(); col_it.forward()) { ColPartition* column = col_it.data(); // Any existing column to the left of column is completed. while (!src_it.empty() && ((working_set = src_it.data())->column() == NULL || working_set->column()->right_key() <= column->left_key())) { src_it.extract(); working_set->ExtractCompletedBlocks(bleft, tright, resolution, used_parts, &completed_blocks, &to_blocks); delete working_set; src_it.forward(); } // Make a new between-column WorkingSet for before the current column. working_set = new WorkingPartSet(NULL); dest_it.add_after_then_move(working_set); if (first_new_set == NULL) first_new_set = working_set; // A matching column gets to stay, and first_new_set gets all the // completed_sets. working_set = src_it.empty() ? NULL : src_it.data(); if (working_set != NULL && working_set->column()->MatchingColumns(*column)) { working_set->set_column(column); dest_it.add_after_then_move(src_it.extract()); src_it.forward(); first_new_set->InsertCompletedBlocks(&completed_blocks, &to_blocks); first_new_set = NULL; } else { // Just make a new working set for the current column. working_set = new WorkingPartSet(column); dest_it.add_after_then_move(working_set); } } // Complete any remaining src working sets. while (!src_it.empty()) { working_set = src_it.extract(); working_set->ExtractCompletedBlocks(bleft, tright, resolution, used_parts, &completed_blocks, &to_blocks); delete working_set; src_it.forward(); } // Make a new between-column WorkingSet for after the last column. working_set = new WorkingPartSet(NULL); dest_it.add_after_then_move(working_set); if (first_new_set == NULL) first_new_set = working_set; // The first_new_set now gets any accumulated completed_parts/blocks. first_new_set->InsertCompletedBlocks(&completed_blocks, &to_blocks); }