29# include "config_auto.h"
40#define partial_split_priority(split) (grade_split_length(split) + grade_sharpness(split))
45#define SPLIT_CLOSENESS 20
47#define MAX_NUM_SEAMS 150
49#define NO_FULL_PRIORITY (-1)
51#define BAD_PRIORITY 9999.0
65 if (new_seam ==
nullptr) {
69 tprintf(
"Pushing new seam with priority %g :", new_priority);
70 new_seam->
Print(
"seam: ");
74 if (seams->
PopWorst(&old_pair) && old_pair.
key() <= new_priority) {
76 tprintf(
"Old seam staying with priority %g\n", old_pair.
key());
79 seams->
Push(&old_pair);
81 }
else if (chop_debug) {
82 tprintf(
"New seam with priority %g beats old worst seam with %g\n", new_priority,
86 SeamPair new_pair(new_priority, new_seam);
87 seams->
Push(&new_pair);
108 my_priority = priority;
109 if (
split !=
nullptr) {
111 split_point +=
split->point2->pos;
113 seam =
new SEAM(my_priority, split_point, *
split);
114 if (chop_debug > 1) {
115 seam->
Print(
"Partial priority ");
119 if (my_priority > chop_good_split) {
126 while (!seam_queue->
empty()) {
128 seam_queue->
Pop(&seam_pair);
133 chop_center_knob, chop_width_change_knob);
136 snprintf(str,
sizeof(str),
"Full my_priority %0.0f, ", my_priority);
140 if ((*seam_result ==
nullptr || (*seam_result)->
priority() > my_priority) &&
141 my_priority < chop_ok_split) {
143 if (seam->
IsHealthy(*blob, chop_min_outline_points, chop_min_outline_area)) {
145 *seam_result =
new SEAM(*seam);
146 (*seam_result)->set_priority(my_priority);
154 if (my_priority < chop_good_split) {
161 if (seam_pile->
size() < chop_seam_pile_size) {
164 seam_pile->
Push(&pair);
165 }
else if (chop_new_seam_pile && seam_pile->
size() == chop_seam_pile_size &&
166 seam_pile->
PeekTop().key() > seam_pair.
key()) {
169 seam_pile->
Pop(&pair);
174 seam_pile->
Push(&pair);
181 if ((my_priority > chop_ok_split) || (my_priority > chop_good_split &&
split)) {
195 for (
int x = 0;
x < seam_pile.
size(); ++
x) {
196 const SEAM *this_one = seam_pile.
get(
x).data();
200 if (chop_debug > 1) {
201 new_one->
Print(
"Combo priority ");
215 SeamPile seam_pile(chop_seam_pile_size);
217 EDGEPT_CLIST new_points;
218 SEAM *seam =
nullptr;
220 int16_t num_points = 0;
222#ifndef GRAPHICS_DISABLED
223 if (chop_debug > 2) {
231 for (outline = blob->
outlines; outline; outline = outline->
next) {
236 points[num_points++] = point_heap.
PeekTop().data();
237 point_heap.
Pop(
nullptr);
243 try_point_pairs(points, num_points, &seam_queue, &seam_pile, &seam, blob);
244 try_vertical_splits(points, num_points, &new_points, &seam_queue, &seam_pile, &seam, blob);
246 if (seam ==
nullptr) {
248 }
else if (seam->
priority() > chop_good_split) {
252 EDGEPT_C_IT it(&new_points);
253 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
254 EDGEPT *inserted_point = it.data();
255 if (seam ==
nullptr || !seam->
UsesPoint(inserted_point)) {
256 for (outline = blob->
outlines; outline; outline = outline->
next) {
257 if (outline->
loop == inserted_point) {
266 if (seam->
priority() > chop_ok_split) {
270#ifndef GRAPHICS_DISABLED
273 if (chop_debug > 2) {
302 for (
x = 0;
x < num_points;
x++) {
303 for (
y =
x + 1;
y < num_points;
y++) {
305 points[
x]->WeightedDistance(*points[
y], chop_x_y_weight) < chop_split_length &&
306 points[
x] != points[
y]->
next && points[
y] != points[
x]->
next &&
328 EDGEPT_CLIST *new_points,
SeamQueue *seam_queue,
330 EDGEPT *vertical_point =
nullptr;
335 for (
x = 0;
x < num_points;
x++) {
336 vertical_point =
nullptr;
337 for (outline = blob->
outlines; outline; outline = outline->
next) {
341 if (vertical_point && points[
x] != vertical_point->
next && vertical_point != points[
x]->
next &&
342 points[
x]->
WeightedDistance(*vertical_point, chop_x_y_weight) < chop_split_length) {
#define partial_split_priority(split)
#define is_exterior_point(edge, point)
void remove_edgept(EDGEPT *point)
void tprintf(const char *format,...)
bool wordrec_display_splits
const std::vector< std::string > split(const std::string &s, char c)
void draw_blob_edges(TBLOB *blob)
int WeightedDistance(const EDGEPT &other, int x_factor) const
TBOX bounding_box() const
void CombineWith(const SEAM &other)
bool UsesPoint(const EDGEPT *point) const
float FullPriority(int xmin, int xmax, double overlap_knob, int centered_maxwidth, double center_knob, double width_change_knob) const
bool CombineableWith(const SEAM &other, int max_x_dist, float max_total_priority) const
void Mark(ScrollView *window) const
bool IsHealthy(const TBLOB &blob, int min_points, int min_area) const
void Print(const char *label) const
bool PopWorst(Pair *entry)
const Pair & PeekTop() const
const Pair & get(int index) const
void set_data(Data *new_data)
void set_key(const Key &new_key)
void add_seam_to_queue(float new_priority, SEAM *new_seam, SeamQueue *seams)
void prioritize_points(TESSLINE *outline, PointHeap *points)
void try_point_pairs(EDGEPT *points[MAX_NUM_POINTS], int16_t num_points, SeamQueue *seam_queue, SeamPile *seam_pile, SEAM **seam, TBLOB *blob)
void try_vertical_splits(EDGEPT *points[MAX_NUM_POINTS], int16_t num_points, EDGEPT_CLIST *new_points, SeamQueue *seam_queue, SeamPile *seam_pile, SEAM **seam, TBLOB *blob)
void combine_seam(const SeamPile &seam_pile, const SEAM *seam, SeamQueue *seam_queue)
void vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point, EDGEPT **best_point, EDGEPT_CLIST *new_points)
SEAM * pick_good_seam(TBLOB *blob)
void choose_best_seam(SeamQueue *seam_queue, const SPLIT *split, PRIORITY priority, SEAM **seam_result, TBLOB *blob, SeamPile *seam_pile)