00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "utilities.h"
00026
00027 static Boolean have_two_corresponding_aux(ElementTypePtr old_element,
00028 ElementTypePtr new_element,
00029 Boolean unique,
00030 Boolean non_coincident,
00031 PadOrPinType* old1_pp_ptr,
00032 PadOrPinType* old2_pp_ptr,
00033 PadOrPinType* new1_pp_ptr,
00034 PadOrPinType* new2_pp_ptr);
00035
00036
00037
00038
00039 PadOrPinType
00040 make_pad_or_pin(PadTypePtr pad, PinTypePtr pin)
00041 {
00042 PadOrPinType pp = { pad, pin };
00043 return pp;
00044 }
00045
00046 Boolean
00047 is_pad_or_pin(const PadOrPinType* pp)
00048 {
00049 return pp->pad || pp->pin;
00050 }
00051
00052 const char*
00053 pad_or_pin_number(const PadOrPinType* pp)
00054 {
00055 if (pp->pad) {
00056 return pp->pad->Number;
00057 } else if (pp->pin) {
00058 return pp->pin->Number;
00059 } else {
00060 return NULL;
00061 }
00062 }
00063
00064 const char*
00065 pad_or_pin_name(const PadOrPinType* pp)
00066 {
00067 if (pp->pad) {
00068 return pp->pad->Name;
00069 } else if (pp->pin) {
00070 return pp->pin->Name;
00071 } else {
00072 return NULL;
00073 }
00074 }
00075
00076 int
00077 number_cmp(const char* number_a, const char* number_b)
00078 {
00079 if (! number_a && ! number_b) {
00080 return 0;
00081 } else if (! number_a) {
00082 return -1;
00083 } else if (! number_b) {
00084 return 1;
00085 } else {
00086 return strcmp(number_a, number_b);
00087 }
00088 }
00089
00090 Boolean
00091 pad_or_pin_test_flag(const PadOrPinType* pp, unsigned long flag)
00092 {
00093 if (pp->pad) {
00094 return TEST_FLAG(flag, pp->pad);
00095 } else if (pp->pin) {
00096 return TEST_FLAG(flag, pp->pin);
00097 } else {
00098 return False;
00099 }
00100 }
00101 void
00102 pad_or_pin_set_flag(PadOrPinType* pp, unsigned long flag)
00103 {
00104 if (pp->pad) {
00105 SET_FLAG(flag, pp->pad);
00106 } else if (pp->pin) {
00107 SET_FLAG(flag, pp->pin);
00108 }
00109 }
00110
00111 int
00112 pad_or_pin_number_cmp(const PadOrPinType* ppa, const PadOrPinType* ppb)
00113 {
00114 return number_cmp(pad_or_pin_number(ppa), pad_or_pin_number(ppb));
00115 }
00116
00117 CheapPointType
00118 pad_or_pin_center(PadOrPinType* pp)
00119 {
00120 if (pp->pad) {
00121 return pad_center(pp->pad);
00122 } else if (pp->pin) {
00123 return pin_center(pp->pin);
00124 } else {
00125 base_log("Error: pad_or_pin_center() got an empty PadOrPinType.\n");
00126 return make_point(0, 0);
00127 }
00128 }
00129
00130 CheapPointType
00131 pad_center(PadTypePtr pad)
00132 {
00133 return make_point((pad->Point1.X + pad->Point2.X) / 2,
00134 (pad->Point1.Y + pad->Point2.Y) / 2);
00135 }
00136
00137 CheapPointType
00138 pin_center(PinTypePtr pin)
00139 {
00140 return MAKE_PT(*pin);
00141 }
00142
00143 Boolean
00144 find_pad_or_pin(ElementTypePtr element, const char* number,
00145 PadOrPinType* pp_ptr)
00146 {
00147 PadOrPinType pp = make_pad_or_pin(NULL, NULL);
00148 if (number &&
00149 ((pp.pad = find_pad(element, number))
00150 || (pp.pin = find_pin(element, number)))) {
00151 *pp_ptr = pp;
00152 return True;
00153 } else {
00154 return False;
00155 }
00156 }
00157
00158 PadTypePtr
00159 find_pad(ElementTypePtr element, const char* number)
00160 {
00161 PAD_LOOP(element);
00162 {
00163 if (pad->Number && number_cmp(pad->Number, number) == 0) {
00164 return pad;
00165 }
00166 }
00167 END_LOOP;
00168 return NULL;
00169 }
00170
00171 PinTypePtr
00172 find_pin(ElementTypePtr element, const char* number)
00173 {
00174 PIN_LOOP(element);
00175 {
00176 if (pin->Number && number_cmp(pin->Number, number) == 0) {
00177 return pin;
00178 }
00179 }
00180 END_LOOP;
00181 return NULL;
00182 }
00183
00184 Boolean
00185 is_number_unique(ElementTypePtr element, const char* number)
00186 {
00187 int count = 0;
00188 PAD_OR_PIN_LOOP(element);
00189 {
00190 const char* pp_number = pad_or_pin_number(&pp);
00191 if (pp_number && number_cmp(pp_number, number) == 0) {
00192 if (++count > 1) {
00193 return False;
00194 }
00195 }
00196 }
00197 END_LOOP;
00198 return True;
00199 }
00200
00201 Boolean
00202 have_two_corresponding_non_coincident(ElementTypePtr old_element,
00203 ElementTypePtr new_element,
00204 PadOrPinType* old1_pp_ptr,
00205 PadOrPinType* old2_pp_ptr,
00206 PadOrPinType* new1_pp_ptr,
00207 PadOrPinType* new2_pp_ptr)
00208 {
00209 return have_two_corresponding_aux(old_element, new_element,
00210 False, True,
00211 old1_pp_ptr, old2_pp_ptr,
00212 new1_pp_ptr, new2_pp_ptr);
00213 }
00214
00215 Boolean
00216 have_two_corresponding_unique_non_coincident(ElementTypePtr old_element,
00217 ElementTypePtr new_element,
00218 PadOrPinType* old1_pp_ptr,
00219 PadOrPinType* old2_pp_ptr,
00220 PadOrPinType* new1_pp_ptr,
00221 PadOrPinType* new2_pp_ptr)
00222 {
00223 return have_two_corresponding_aux(old_element, new_element,
00224 True, True,
00225 old1_pp_ptr, old2_pp_ptr,
00226 new1_pp_ptr, new2_pp_ptr);
00227 }
00228
00229 static Boolean
00230 have_two_corresponding_aux(ElementTypePtr old_element,
00231 ElementTypePtr new_element,
00232 Boolean unique,
00233 Boolean non_coincident,
00234 PadOrPinType* old1_pp_ptr,
00235 PadOrPinType* old2_pp_ptr,
00236 PadOrPinType* new1_pp_ptr,
00237 PadOrPinType* new2_pp_ptr)
00238 {
00239 PadOrPinType old1_pp = make_pad_or_pin(NULL, NULL);
00240 PadOrPinType new1_pp = make_pad_or_pin(NULL, NULL);
00241 Boolean first_found = False;
00242
00243 PAD_OR_PIN_LOOP_HYG(old_element, _old);
00244 {
00245 if (! unique
00246 || is_number_unique(old_element,
00247 pad_or_pin_number(&pp_old))) {
00248 CheapPointType old_pt = pad_or_pin_center(&pp_old);
00249 PAD_OR_PIN_LOOP_HYG(new_element, _new);
00250 {
00251 if (pad_or_pin_number_cmp(&pp_old, &pp_new) == 0
00252 && (! unique
00253 || is_number_unique(new_element,
00254 pad_or_pin_number(&pp_new)))) {
00255 CheapPointType new_pt = pad_or_pin_center(&pp_new);
00256 if (! non_coincident || point_distance2(old_pt, new_pt)) {
00257 if (! first_found) {
00258 old1_pp = pp_old;
00259 new1_pp = pp_new;
00260 first_found = True;
00261 } else {
00262 if (old1_pp_ptr) {
00263 *old1_pp_ptr = old1_pp;
00264 }
00265 if (new1_pp_ptr) {
00266 *new1_pp_ptr = new1_pp;
00267 }
00268 if (old2_pp_ptr) {
00269 *old2_pp_ptr = pp_old;
00270 }
00271 if (new2_pp_ptr) {
00272 *new2_pp_ptr = pp_new;
00273 }
00274 return True;
00275 }
00276 }
00277 }
00278 }
00279 END_LOOP;
00280 }
00281 }
00282 END_LOOP;
00283 return False;
00284 }
00285
00286 Boolean
00287 have_any_corresponding_pad_or_pin(ElementTypePtr old_element,
00288 ElementTypePtr new_element,
00289 PadOrPinType* old_pp,
00290 PadOrPinType* new_pp)
00291 {
00292 PAD_OR_PIN_LOOP_HYG(old_element, _old);
00293 {
00294 PAD_OR_PIN_LOOP_HYG(new_element, _new);
00295 {
00296 if (pad_or_pin_number_cmp(&pp_old, &pp_new) == 0) {
00297 if (old_pp) {
00298 *old_pp = pp_old;
00299 }
00300 if (new_pp) {
00301 *new_pp = pp_new;
00302 }
00303 return True;
00304 }
00305 }
00306 END_LOOP;
00307 }
00308 END_LOOP;
00309 return False;
00310 }
00311
00312
00313
00314
00315
00316 CheapPointType
00317 make_point(LocationType x, LocationType y)
00318 {
00319 CheapPointType pt = { x, y };
00320 return pt;
00321 }
00322
00323 CheapPointType
00324 point_subtract(CheapPointType pt1, CheapPointType pt2)
00325 {
00326 return make_point(pt1.X - pt2.X, pt1.Y - pt2.Y);
00327 }
00328
00329
00330 double
00331 point_distance2(CheapPointType pt1, CheapPointType pt2)
00332 {
00333 CheapPointType diff = point_subtract(pt1, pt2);
00334 return (double)diff.X * (double)diff.X + (double)diff.Y * (double)diff.Y;
00335 }
00336
00337
00338
00339
00340
00341 double
00342 round(double v)
00343 {
00344 if (v < 0) {
00345 return ceil(v - 0.5);
00346 } else {
00347 return floor(v + 0.5);
00348 }
00349 }
00350
00351 double
00352 multiple_of_90(double rad)
00353 {
00354 return (M_PI / 2) * round(rad / (M_PI / 2));
00355 }
00356
00357 #define ANGLE_EPSILON 0.01
00358 #define ANGLE_NEAR(a1, a2) (fabs((a1) - (a2)) < ANGLE_EPSILON)
00359
00360 BYTE
00361 angle_to_rotation_steps(double rad)
00362 {
00363 double rad90 = multiple_of_90(rad);
00364
00365 if (ANGLE_NEAR(rad90, M_PI / 2)) {
00366 return 3;
00367 } else if (ANGLE_NEAR(fabs(rad90), M_PI)) {
00368 return 2;
00369 } else if (ANGLE_NEAR(rad90, -M_PI / 2)) {
00370 return 1;
00371 } else if (ANGLE_NEAR(rad90, 0)) {
00372 return 0;
00373 } else {
00374 base_log("Error: angle_to_rotation_steps() got "
00375 "an unhandled angle: %lf\n",
00376 rad * RAD_TO_DEG);
00377 return 0;
00378 }
00379 }
00380
00381
00382
00383
00384
00385 void
00386 log_point(CheapPointType pt)
00387 {
00388 base_log("Point\n");
00389 base_log("%8d %8d\n", pt.X, pt.Y);
00390 }
00391
00392 void
00393 log_pad_or_pin(const PadOrPinType* pp)
00394 {
00395 if (pp->pad) {
00396 log_pad(pp->pad);
00397 } else {
00398 log_pin(pp->pin);
00399 }
00400 }
00401
00402 void
00403 log_pad(PadTypePtr p)
00404 {
00405 base_log("Pad\n");
00406 base_log("Name: \"%s\"\n", p->Name);
00407 base_log("Number: \"%s\"\n", p->Number);
00408 base_log("Point 1: (%d, %d)\n", p->Point1.X, p->Point1.Y);
00409 base_log("Point 2: (%d, %d)\n", p->Point2.X, p->Point2.Y);
00410 }
00411
00412 void
00413 log_pin(PinTypePtr p)
00414 {
00415 base_log("Pin\n");
00416 base_log("Name: \"%s\"\n", p->Name);
00417 base_log("Number: \"%s\"\n", p->Number);
00418 base_log("Point: (%d, %d)\n", p->X, p->Y);
00419 }
00420
00421 void
00422 log_element(ElementTypePtr e)
00423 {
00424 base_log("Element\n");
00425 base_log("Description: %s\n", DESCRIPTION_NAME(e));
00426 base_log("Name on PCB: %s\n", NAMEONPCB_NAME(e));
00427 base_log("Value: %s\n", VALUE_NAME(e));
00428 base_log("Flags: %04x\n", FLAG_VALUE(e->Flags));
00429 base_log("MarkX, MarkY: %d, %d\n", e->MarkX, e->MarkY);
00430 base_log("PinN: %d\n", e->PinN);
00431 base_log("PadN: %d\n", e->PadN);
00432 base_log("LineN: %d\n", e->LineN);
00433 base_log("ArcN: %d\n", e->ArcN);
00434 base_log("Attributes number: %d\n", e->Attributes.Number);
00435
00436 int i = 0;
00437 PAD_LOOP(e);
00438 {
00439 base_log("Pad %d\n", i++);
00440 log_pad(pad);
00441 }
00442 END_LOOP;
00443
00444 i = 0;
00445 PIN_LOOP(e);
00446 {
00447 base_log("Pin %d\n", i++);
00448 log_pin(pin);
00449 }
00450 END_LOOP;
00451 }
00452
00453 void base_log(const char *fmt, ...)
00454 {
00455 va_list args;
00456 va_start(args, fmt);
00457 gui->log(TITLE);
00458 gui->log(": ");
00459 gui->logv(fmt, args);
00460 #if DEBUG
00461
00462 vfprintf(stderr, fmt, args);
00463 #endif
00464 va_end(args);
00465 }
00466
00467 void debug_log(const char *fmt, ...)
00468 {
00469 va_list args;
00470 va_start(args, fmt);
00471 #if DEBUG
00472 gui->log(TITLE);
00473 gui->log(": ");
00474 gui->logv(fmt, args);
00475
00476 vfprintf(stderr, fmt, args);
00477 #endif
00478 va_end(args);
00479 }