00001
00021
00022
00023
00024 #include "chop.h"
00025 #include "debug.h"
00026 #include "outlines.h"
00027 #include "olutil.h"
00028 #include "tordvars.h"
00029 #include "callcpp.h"
00030 #include "plotedges.h"
00031 #include "const.h"
00032
00033 #include <math.h>
00034
00035
00036
00037
00038
00041 make_int_var (chop_debug, 0, make_chop_debug,
00042 3, 1, set_chop_debug, "Chop debug");
00043 make_int_var (chop_enable, 1, make_chop_enable,
00044 3, 2, set_chop_enable, "Chop enable");
00045 make_toggle_var (vertical_creep, 0, make_vertical_creep,
00046 3, 4, set_vertical_creep, "Vertical creep");
00047 make_int_var (split_length, 10000, make_split_length,
00048 3, 5, set_split_length, "Split Length");
00049 make_int_var (same_distance, 2, make_same_distance,
00050 3, 6, set_same_distance, "Same distance");
00051 make_int_var (min_outline_points, 6, make_min_points,
00052 3, 9, set_min_points, "Min Number of Points on Outline");
00053 make_int_var (inside_angle, -50, make_inside_angle,
00054 3, 12, set_inside_angle, "Min Inside Angle Bend");
00055 make_int_var (min_outline_area, 2000, make_outline_area,
00056 3, 13, set_outline_area, "Min Outline Area");
00059
00060
00061
00064 make_float_var (split_dist_knob, 0.5, make_split_dist,
00065 3, 17, set_split_dist, "Split length adjustment");
00066 make_float_var (overlap_knob, 0.9, make_overlap_knob,
00067 3, 18, set_overlap_knob, "Split overlap adjustment");
00068 make_float_var (center_knob, 0.15, make_center_knob,
00069 3, 19, set_center_knob, "Split center adjustment");
00070 make_float_var (sharpness_knob, 0.06, make_sharpness_knob,
00071 3, 20, set_sharpness_knob, "Split sharpness adjustment");
00072 make_float_var (width_change_knob, 5.0, make_width_change,
00073 3, 21, set_width_change_knob, "Width change adjustment");
00074 make_float_var (ok_split, 100.0, make_ok_split,
00075 3, 14, set_ok_split, "OK split limit");
00076 make_float_var (good_split, 50.0, make_good_split,
00077 3, 15, set_good_split, "Good split limit");
00078 make_int_var (x_y_weight, 3, make_x_y_weight,
00079 3, 16, set_x_y_weight, "X / Y length weight");
00082
00083
00084
00085
00092 #define length_product(p1,p2) \
00093 (sqrt ((((float) (p1).x * (p1).x + (float) (p1).y * (p1).y) * \
00094 ((float) (p2).x * (p2).x + (float) (p2).y * (p2).y))))
00095
00096
00097
00098
00099
00106 PRIORITY point_priority(EDGEPT *point) {
00107 return ((PRIORITY) point_bend_angle (point));
00108 }
00109
00110
00111
00115 void add_point_to_list(POINT_GROUP point_list, EDGEPT *point) {
00116 HEAPENTRY data;
00117
00118 if (SizeOfHeap (point_list) < MAX_NUM_POINTS - 2) {
00119 data.Data = (char *) point;
00120 data.Key = point_priority (point);
00121 HeapStore(point_list, &data);
00122 }
00123
00124 #ifndef GRAPHICS_DISABLED
00125 if (chop_debug)
00126 mark_outline(point);
00127 #endif
00128 }
00129
00130
00131
00136 int angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3) {
00137 VECTOR vector1;
00138 VECTOR vector2;
00139
00140 int angle;
00141 float length;
00142
00143
00144 vector1.x = point2->pos.x - point1->pos.x;
00145 vector1.y = point2->pos.y - point1->pos.y;
00146 vector2.x = point3->pos.x - point2->pos.x;
00147 vector2.y = point3->pos.y - point2->pos.y;
00148
00149 length = length_product (vector1, vector2);
00150 if ((int) length == 0)
00151 return (0);
00152 angle = (int) (asin (CROSS (vector1, vector2) / length) / PI * 180.0);
00153
00154
00155 if (SCALAR (vector1, vector2) < 0)
00156 angle = 180 - angle;
00157
00158 if (angle > 180)
00159 angle -= 360;
00160 if (angle <= -180)
00161 angle += 360;
00162 return (angle);
00163 }
00164
00165
00166
00170 void init_chop() {
00171 make_same_distance();
00172 make_vertical_creep();
00173 make_x_y_weight();
00174 make_chop_enable();
00175 make_chop_debug();
00176 make_split_dist();
00177 make_overlap_knob();
00178 make_sharpness_knob();
00179 make_width_change();
00180 make_good_split();
00181 make_ok_split();
00182 make_center_knob();
00183 make_split_length();
00184 make_min_points();
00185 make_inside_angle();
00186 make_outline_area();
00187 }
00188
00189
00190
00195 int is_little_chunk(EDGEPT *point1, EDGEPT *point2) {
00196 EDGEPT *p = point1;
00197 int counter = 0;
00198
00199 do {
00200
00201 if (is_same_edgept (point2, p)) {
00202 if (is_small_area (point1, point2))
00203 return (TRUE);
00204 else
00205 break;
00206 }
00207 p = p->next;
00208 }
00209 while ((p != point1) && (counter++ < min_outline_points));
00210
00211 p = point2;
00212 counter = 0;
00213 do {
00214 if (is_same_edgept (point1, p)) {
00215 return (is_small_area (point2, point1));
00216 }
00217 p = p->next;
00218 }
00219 while ((p != point2) && (counter++ < min_outline_points));
00220
00221 return (FALSE);
00222 }
00223
00224
00225
00229 int is_small_area(EDGEPT *point1, EDGEPT *point2) {
00230 EDGEPT *p = point1->next;
00231 int area = 0;
00232 TPOINT origin;
00233
00234 do {
00235
00236 origin.x = p->pos.x - point1->pos.x;
00237 origin.y = p->pos.y - point1->pos.y;
00238 area += CROSS (origin, p->vec);
00239 p = p->next;
00240 }
00241 while (!is_same_edgept (point2, p));
00242
00243 return (area < min_outline_area);
00244 }
00245
00246
00247
00253 EDGEPT *pick_close_point(EDGEPT *critical_point,
00254 EDGEPT *vertical_point,
00255 int *best_dist) {
00256 EDGEPT *best_point = NULL;
00257 int this_distance;
00258 int found_better;
00259
00260 do {
00261 found_better = FALSE;
00262
00263 this_distance = edgept_dist (critical_point, vertical_point);
00264 if (this_distance <= *best_dist) {
00265
00266 if (!(same_point (critical_point->pos, vertical_point->pos) ||
00267 same_point (critical_point->pos, vertical_point->next->pos)
00268 || best_point != NULL
00269 && same_point (best_point->pos, vertical_point->pos) ||
00270 is_exterior_point (critical_point, vertical_point))) {
00271 *best_dist = this_distance;
00272 best_point = vertical_point;
00273 if (vertical_creep)
00274 found_better = TRUE;
00275 }
00276 }
00277 vertical_point = vertical_point->next;
00278 }
00279 while (found_better == TRUE);
00280
00281 return (best_point);
00282 }
00283
00284
00285
00292 void prioritize_points(TESSLINE *outline, POINT_GROUP points) {
00293 EDGEPT *this_point;
00294 EDGEPT *local_min = NULL;
00295 EDGEPT *local_max = NULL;
00296
00297 this_point = outline->loop;
00298 local_min = this_point;
00299 local_max = this_point;
00300 do {
00301 if (debug_5)
00302 cprintf ("(%3d,%3d) min=%3d, max=%3d, dir=%2d, ang=%2.0f\n",
00303 this_point->pos.x, this_point->pos.y,
00304 (local_min ? local_min->pos.y : 999),
00305 (local_max ? local_max->pos.y : 999),
00306 direction (this_point), point_priority (this_point));
00307
00308 if (this_point->vec.y < 0) {
00309
00310 if (local_max != NULL)
00311 new_max_point(local_max, points);
00312 else if (is_inside_angle (this_point))
00313 add_point_to_list(points, this_point);
00314 local_max = NULL;
00315 local_min = this_point->next;
00316 }
00317 else if (this_point->vec.y > 0) {
00318
00319 if (local_min != NULL)
00320 new_min_point(local_min, points);
00321 else if (is_inside_angle (this_point))
00322 add_point_to_list(points, this_point);
00323 local_min = NULL;
00324 local_max = this_point->next;
00325 }
00326 else {
00327
00328 if (local_max != NULL) {
00329 if (local_max->prev->vec.y != 0) {
00330 new_max_point(local_max, points);
00331 }
00332 local_max = this_point->next;
00333 local_min = NULL;
00334 }
00335 else {
00336 if (local_min->prev->vec.y != 0) {
00337 new_min_point(local_min, points);
00338 }
00339 local_min = this_point->next;
00340 local_max = NULL;
00341 }
00342 }
00343
00344
00345 this_point = this_point->next;
00346 }
00347 while (this_point != outline->loop);
00348 }
00349
00350
00351
00358 void new_min_point(EDGEPT *local_min, POINT_GROUP points) {
00359 INT16 dir;
00360
00361 dir = direction (local_min);
00362
00363 if (dir < 0) {
00364 add_point_to_list(points, local_min);
00365 return;
00366 }
00367
00368 if (dir == 0 && point_priority (local_min) < 0) {
00369 add_point_to_list(points, local_min);
00370 return;
00371 }
00372 }
00373
00374
00375
00382 void new_max_point(EDGEPT *local_max, POINT_GROUP points) {
00383 INT16 dir;
00384
00385 dir = direction (local_max);
00386
00387 if (dir > 0) {
00388 add_point_to_list(points, local_max);
00389 return;
00390 }
00391
00392 if (dir == 0 && point_priority (local_max) < 0) {
00393 add_point_to_list(points, local_max);
00394 return;
00395 }
00396 }
00397
00398
00399
00418 void vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
00419 EDGEPT** best_point) {
00420 EDGEPT *p;
00421 EDGEPT *this_edgept;
00422 int x = split_point->pos.x;
00423 int best_dist = LARGE_DISTANCE;
00424
00425 if (*best_point != NULL)
00426 best_dist = edgept_dist(split_point, *best_point);
00427
00428 p = target_point;
00429
00430 do {
00431 if ((((p->pos.x <= x) && (x <= p->next->pos.x)) ||
00432 ((p->next->pos.x <= x) && (x <= p->pos.x))) &&
00433 !same_point (split_point->pos, p->pos) &&
00434 !same_point (split_point->pos, p->next->pos)
00435 && (*best_point == NULL || !same_point ((*best_point)->pos, p->pos))) {
00436
00437 this_edgept = near_point (split_point, p, p->next);
00438
00439 if (*best_point == NULL)
00440 best_dist = edgept_dist (split_point, this_edgept);
00441
00442 this_edgept =
00443 pick_close_point(split_point, this_edgept, &best_dist);
00444 if (this_edgept)
00445 *best_point = this_edgept;
00446 }
00447
00448 p = p->next;
00449 }
00450 while (p != target_point);
00451 }