libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00025 #include <config.h> 00026 00027 #include <stdio.h> 00028 #include <math.h> 00029 00030 #include "libgeda_priv.h" 00031 00032 #ifdef HAVE_LIBDMALLOC 00033 #include <dmalloc.h> 00034 #endif 00035 00064 OBJECT *o_arc_new(TOPLEVEL *toplevel, 00065 char type, int color, 00066 int x, int y, int radius, int start_angle, int end_angle) 00067 { 00068 00069 OBJECT *new_node; 00070 00071 new_node = s_basic_new_object(type, "arc"); 00072 00073 new_node->color = color; 00074 00075 new_node->arc = (ARC *) g_malloc(sizeof(ARC)); 00076 00085 /* World coordinates */ 00086 new_node->arc->x = x; 00087 new_node->arc->y = y; 00088 new_node->arc->width = 2 * radius; 00089 new_node->arc->height = 2 * radius; 00090 00091 /* must check the sign of start_angle, end_angle ... */ 00092 if(end_angle < 0) { 00093 start_angle = start_angle + end_angle; 00094 end_angle = -end_angle; 00095 } 00096 if(start_angle < 0) start_angle = 360 + start_angle; 00097 00098 new_node->arc->start_angle = start_angle; 00099 new_node->arc->end_angle = end_angle; 00100 00101 /* Default init */ 00102 o_set_line_options(toplevel, new_node, 00103 END_NONE, TYPE_SOLID, 0, -1, -1); 00104 o_set_fill_options(toplevel, new_node, 00105 FILLING_HOLLOW, -1, -1, -1, -1, -1); 00106 00107 o_arc_recalc(toplevel, new_node); 00108 00109 /* new_node->graphical = arc; eventually */ 00110 00111 return new_node; 00112 } 00113 00127 OBJECT *o_arc_copy(TOPLEVEL *toplevel, OBJECT *o_current) 00128 { 00129 OBJECT *new_obj; 00130 00131 new_obj = o_arc_new (toplevel, OBJ_ARC, o_current->color, 00132 o_current->arc->x, o_current->arc->y, 00133 o_current->arc->width / 2, 00134 o_current->arc->start_angle, 00135 o_current->arc->end_angle); 00136 o_set_line_options(toplevel, new_obj, 00137 o_current->line_end, o_current->line_type, 00138 o_current->line_width, 00139 o_current->line_length, o_current->line_space); 00140 o_set_fill_options(toplevel, new_obj, 00141 FILLING_HOLLOW, -1, -1, -1, -1, -1); 00142 00143 return new_obj; 00144 } 00145 00171 void o_arc_modify(TOPLEVEL *toplevel, OBJECT *object, 00172 int x, int y, int whichone) 00173 { 00174 00175 o_emit_pre_change_notify (toplevel, object); 00176 00177 switch(whichone) { 00178 case ARC_CENTER: 00179 /* modify the center of arc object */ 00180 object->arc->x = x; 00181 object->arc->y = y; 00182 break; 00183 00184 case ARC_RADIUS: 00185 /* modify the radius of arc object */ 00186 object->arc->width = 2 * x; 00187 object->arc->height = 2 * x; 00188 break; 00189 00190 case ARC_START_ANGLE: 00191 /* modify the start angle of the arc object */ 00192 object->arc->start_angle = x; 00193 break; 00194 00195 case ARC_END_ANGLE: 00196 /* modify the end angle of the arc object */ 00197 object->arc->end_angle = x; 00198 break; 00199 00200 default: 00201 break; 00202 } 00203 00204 /* update the screen coords and the bounding box */ 00205 o_arc_recalc(toplevel, object); 00206 o_emit_change_notify (toplevel, object); 00207 } 00208 00235 OBJECT *o_arc_read (TOPLEVEL *toplevel, const char buf[], 00236 unsigned int release_ver, unsigned int fileformat_ver, GError **err) 00237 { 00238 OBJECT *new_obj; 00239 char type; 00240 int x1, y1; 00241 int radius; 00242 int start_angle, end_angle; 00243 int color; 00244 int arc_width, arc_length, arc_space; 00245 int arc_type; 00246 int arc_end; 00247 00253 if(release_ver <= VERSION_20000704) { 00254 if (sscanf(buf, "%c %d %d %d %d %d %d", &type, 00255 &x1, &y1, &radius, &start_angle, &end_angle, &color) != 7) { 00256 g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse arc object")); 00257 return NULL; 00258 } 00259 00260 arc_width = 0; 00261 arc_end = END_NONE; 00262 arc_type = TYPE_SOLID; 00263 arc_space = -1; 00264 arc_length= -1; 00265 } else { 00266 if (sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d", &type, 00267 &x1, &y1, &radius, &start_angle, &end_angle, &color, 00268 &arc_width, &arc_end, &arc_type, &arc_length, &arc_space) != 12) { 00269 g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse arc object")); 00270 return NULL; 00271 } 00272 } 00273 00274 /* Error check */ 00275 if (radius <= 0) { 00276 s_log_message (_("Found a zero radius arc [ %c %d, %d, %d, %d, %d, %d ]\n"), 00277 type, x1, y1, radius, start_angle, end_angle, color); 00278 radius = 0; 00279 } 00280 00281 if (color < 0 || color > MAX_COLORS) { 00282 s_log_message(_("Found an invalid color [ %s ]\n"), buf); 00283 s_log_message(_("Setting color to default color\n")); 00284 color = DEFAULT_COLOR; 00285 } 00286 00287 /* Allocation and initialization */ 00288 new_obj = o_arc_new(toplevel, OBJ_ARC, color, 00289 x1, y1, radius, start_angle, end_angle); 00290 o_set_line_options(toplevel, new_obj, 00291 arc_end, arc_type, arc_width, arc_length, 00292 arc_space); 00293 o_set_fill_options(toplevel, new_obj, 00294 FILLING_HOLLOW, -1, -1, -1, 00295 -1, -1); 00296 00297 return new_obj; 00298 } 00299 00311 char *o_arc_save(TOPLEVEL *toplevel, OBJECT *object) 00312 { 00313 int x, y, radius, start_angle, end_angle; 00314 int arc_width, arc_length, arc_space; 00315 char *buf; 00316 OBJECT_END arc_end; 00317 OBJECT_TYPE arc_type; 00318 00319 /* radius, center and angles of the arc */ 00320 radius = object->arc->width / 2; 00321 x = object->arc->x; 00322 y = object->arc->y; 00323 start_angle = object->arc->start_angle; 00324 end_angle = object->arc->end_angle; 00325 00326 /* line type parameters */ 00327 arc_width = object->line_width; 00328 arc_end = object->line_end; 00329 arc_type = object->line_type; 00330 arc_length = object->line_length; 00331 arc_space = object->line_space; 00332 00333 /* Describe a circle with post-20000704 file format */ 00334 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d", object->type, 00335 x, y, radius, start_angle, end_angle, object->color, 00336 arc_width, arc_end, arc_type, arc_length, arc_space); 00337 00338 return(buf); 00339 } 00340 00351 void o_arc_translate_world(TOPLEVEL *toplevel, int dx, int dy, 00352 OBJECT *object) 00353 { 00354 if (object == NULL) { 00355 return; 00356 } 00357 00358 /* Do world coords */ 00359 object->arc->x = object->arc->x + dx; 00360 object->arc->y = object->arc->y + dy; 00361 00362 00363 /* Recalculate screen coords from new world coords */ 00364 o_arc_recalc(toplevel, object); 00365 } 00366 00387 void o_arc_rotate_world(TOPLEVEL *toplevel, 00388 int world_centerx, int world_centery, int angle, 00389 OBJECT *object) 00390 { 00391 int x, y, newx, newy; 00392 00393 /* translate object to origin */ 00394 object->arc->x -= world_centerx; 00395 object->arc->y -= world_centery; 00396 00397 /* get center, and rotate center */ 00398 x = object->arc->x; 00399 y = object->arc->y; 00400 if(angle % 90 == 0) { 00401 rotate_point_90(x, y, angle % 360, &newx, &newy); 00402 } else { 00403 rotate_point(x, y, angle % 360, &newx, &newy); 00404 } 00405 object->arc->x = newx; 00406 object->arc->y = newy; 00407 00408 /* apply rotation to angles */ 00409 object->arc->start_angle = (object->arc->start_angle + angle) % 360; 00410 /* end_angle is unchanged as it is the sweep of the arc */ 00411 /* object->arc->end_angle = (object->arc->end_angle); */ 00412 00413 /* translate object to its previous place */ 00414 object->arc->x += world_centerx; 00415 object->arc->y += world_centery; 00416 00417 /* update the screen coords and the bounding box */ 00418 o_arc_recalc(toplevel, object); 00419 00420 } 00421 00438 void o_arc_mirror_world(TOPLEVEL *toplevel, 00439 int world_centerx, int world_centery, 00440 OBJECT *object) 00441 { 00442 /* translate object to origin */ 00443 object->arc->x -= world_centerx; 00444 object->arc->y -= world_centery; 00445 00446 /* get center, and mirror it (vertical mirror) */ 00447 object->arc->x = -object->arc->x; 00448 object->arc->y = object->arc->y; 00449 00450 /* apply mirror to angles (vertical mirror) */ 00451 object->arc->start_angle = (180 - object->arc->start_angle) % 360; 00452 /* start_angle *MUST* be positive */ 00453 if(object->arc->start_angle < 0) object->arc->start_angle += 360; 00454 object->arc->end_angle = -object->arc->end_angle; 00455 00456 /* translate object back to its previous position */ 00457 object->arc->x += world_centerx; 00458 object->arc->y += world_centery; 00459 00460 /* update the screen coords and bounding box */ 00461 o_arc_recalc(toplevel, object); 00462 00463 } 00464 00478 void o_arc_recalc(TOPLEVEL *toplevel, OBJECT *o_current) 00479 { 00480 int left, right, top, bottom; 00481 00482 if (o_current->arc == NULL) { 00483 return; 00484 } 00485 00486 /* recalculates the bounding box */ 00487 world_get_arc_bounds(toplevel, o_current, &left, &top, &right, &bottom); 00488 o_current->w_left = left; 00489 o_current->w_top = top; 00490 o_current->w_right = right; 00491 o_current->w_bottom = bottom; 00492 o_current->w_bounds_valid = TRUE; 00493 } 00494 00495 00514 void world_get_arc_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, 00515 int *top, int *right, int *bottom) 00516 { 00517 int x1, y1, x2, y2, x3, y3; 00518 int radius, start_angle, end_angle; 00519 int i, angle; 00520 int halfwidth; 00521 00522 halfwidth = object->line_width / 2; 00523 00524 radius = object->arc->width / 2; 00525 start_angle = object->arc->start_angle; 00526 end_angle = object->arc->end_angle; 00527 00528 x1 = object->arc->x; 00529 y1 = object->arc->y; 00530 x2 = x1 + radius * cos(start_angle * M_PI / 180); 00531 y2 = y1 + radius * sin(start_angle * M_PI / 180); 00532 x3 = x1 + radius * cos((start_angle + end_angle) * M_PI / 180); 00533 y3 = y1 + radius * sin((start_angle + end_angle) * M_PI / 180); 00534 00535 *left = (x1 < x2) ? ((x1 < x3) ? x1 : x3) : ((x2 < x3) ? x2 : x3); 00536 *right = (x1 > x2) ? ((x1 > x3) ? x1 : x3) : ((x2 > x3) ? x2 : x3); 00537 *bottom = (y1 > y2) ? ((y1 > y3) ? y1 : y3) : ((y2 > y3) ? y2 : y3); 00538 *top = (y1 < y2) ? ((y1 < y3) ? y1 : y3) : ((y2 < y3) ? y2 : y3); 00539 00549 if (end_angle < 0) { 00550 start_angle = (start_angle + end_angle + 360) % 360; 00551 end_angle = -end_angle; 00552 } 00553 angle = ((int) (start_angle / 90)) * 90; 00554 for(i = 0; i < 4; i++) { 00555 angle = angle + 90; 00556 if(angle < start_angle + end_angle) { 00557 if(angle % 360 == 0) *right = x1 + radius; 00558 if(angle % 360 == 90) *bottom = y1 + radius; 00559 if(angle % 360 == 180) *left = x1 - radius; 00560 if(angle % 360 == 270) *top = y1 - radius; 00561 } else { 00562 break; 00563 } 00564 } 00565 00566 /* This isn't strictly correct, but a 1st order approximation */ 00567 *left -= halfwidth; 00568 *top -= halfwidth; 00569 *right += halfwidth; 00570 *bottom += halfwidth; 00571 00572 } 00573 00584 gboolean o_arc_get_position (TOPLEVEL *toplevel, gint *x, gint *y, 00585 OBJECT *object) 00586 { 00587 *x = object->arc->x; 00588 *y = object->arc->y; 00589 return TRUE; 00590 } 00591 00607 void o_arc_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, 00608 int origin_x, int origin_y) 00609 { 00610 int x, y, radius, start_angle, end_angle; 00611 int color; 00612 int arc_width, space, length; 00613 void (*outl_func)() = NULL; 00614 00615 if (o_current == NULL) { 00616 printf("got null in o_arc_print\n"); 00617 return; 00618 } 00619 00620 x = o_current->arc->x; 00621 y = o_current->arc->y; 00622 radius = o_current->arc->width / 2; 00623 start_angle = o_current->arc->start_angle; 00624 end_angle = o_current->arc->end_angle; 00625 color = o_current->color; 00626 00639 #if 0 /* was causing arcs which are solid to be much thinner compared to */ 00640 /* lines, boxes, also of zero width */ 00641 if (o_current->line_width > 0) { 00642 arc_width = o_current->line_width; 00643 } else { 00644 arc_width = 1; 00645 } 00646 #endif 00647 arc_width = o_current->line_width; /* Added instead of above */ 00648 if(arc_width <=2) { 00649 if(toplevel->line_style == THICK) { 00650 arc_width=LINE_WIDTH; 00651 } else { 00652 arc_width=2; 00653 } 00654 } 00655 00656 length = o_current->line_length; 00657 space = o_current->line_space; 00658 00659 switch(o_current->line_type) { 00660 case(TYPE_SOLID): 00661 length = -1; space = -1; 00662 outl_func = o_arc_print_solid; 00663 break; 00664 00665 case(TYPE_DOTTED): 00666 length = -1; 00667 outl_func = o_arc_print_dotted; 00668 break; 00669 00670 case(TYPE_DASHED): 00671 outl_func = o_arc_print_dashed; 00672 break; 00673 00674 case(TYPE_CENTER): 00675 outl_func = o_arc_print_center; 00676 break; 00677 00678 case(TYPE_PHANTOM): 00679 outl_func = o_arc_print_phantom; 00680 break; 00681 00682 case(TYPE_ERASE): 00683 /* Unused for now, print it solid */ 00684 length = -1; space = -1; 00685 outl_func = o_arc_print_solid; 00686 break; 00687 } 00688 00689 if((space == 0) || (length == 0)) { 00690 length = -1; space = -1; 00691 outl_func = o_arc_print_solid; 00692 } 00693 00694 (*outl_func)(toplevel, fp, 00695 x - origin_x, y - origin_x, radius, 00696 start_angle, end_angle, 00697 color, arc_width, length, space, origin_x, origin_y); 00698 } 00699 00700 00727 void o_arc_print_solid(TOPLEVEL *toplevel, FILE *fp, 00728 int x, int y, int radius, 00729 int angle1, int angle2, 00730 int color, 00731 int arc_width, int length, int space, 00732 int origin_x, int origin_y) 00733 { 00734 f_print_set_color(toplevel, fp, color); 00735 00736 /* inverting angle2 if < 0 and changing angle1 accordingly */ 00737 if (angle2 < 0) { 00738 angle1 = angle1 + angle2; 00739 angle2 = -angle2; 00740 } 00741 00742 fprintf(fp, "%d %d %d %d %d %d darc\n", 00743 x,y, radius, angle1, angle1 + angle2, 00744 arc_width); 00745 00746 } 00747 00778 void o_arc_print_dotted(TOPLEVEL *toplevel, FILE *fp, 00779 int x, int y, int radius, 00780 int angle1, int angle2, 00781 int color, 00782 int arc_width, int length, int space, 00783 int origin_x, int origin_y) 00784 { 00785 int da, d; 00786 00787 f_print_set_color(toplevel, fp, color); 00788 00801 /* Inverting angle2 if < 0 and changing angle1 accordingly */ 00802 /* the loop test assume that da > 0 */ 00803 if (angle2 < 0) { 00804 angle1 = angle1 + angle2; 00805 angle2 = -angle2; 00806 } 00807 da = (int) ((space * 180) / (M_PI * ((double) radius))); 00808 00809 /* If da or db too small for arc to be displayed as dotted, 00810 draw a solid arc */ 00811 if (da <= 0) { 00812 o_arc_print_solid(toplevel, fp, 00813 x, y, radius, 00814 angle1, angle2, 00815 color, 00816 arc_width, length, space, origin_x, origin_y); 00817 return; 00818 } 00819 00820 fprintf(fp,"["); 00821 d = angle1; 00822 while (d < (angle2 + angle1)) { 00823 /*xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180); 00824 ya = ((double) y) + ((double) radius) * sin(d * M_PI / 180); 00825 */ 00826 fprintf(fp,"[%d] ",d); 00827 00828 d = d + da; 00829 } 00830 fprintf(fp,"] %d %d %d %d dashedarc %% dotted\n", 00831 x,y, radius, arc_width); 00832 } 00833 00862 void o_arc_print_dashed(TOPLEVEL *toplevel, FILE *fp, 00863 int x, int y, int radius, 00864 int angle1, int angle2, 00865 int color, 00866 int arc_width, int length, int space, 00867 int origin_x, int origin_y) 00868 { 00869 int da, db, a1, d; 00870 00871 f_print_set_color(toplevel, fp, color); 00872 00887 /* Inverting angle2 if < 0 and changing angle1 accordingly */ 00888 /* the loop test assume that da > 0 */ 00889 if (angle2 < 0) { 00890 angle1 = angle1 + angle2; 00891 angle2 = -angle2; 00892 } 00893 da = (int) ((length * 180) / (M_PI * ((double) radius))); 00894 db = (int) ((space * 180) / (M_PI * ((double) radius))); 00895 00896 /* If da or db too small for arc to be displayed as dotted, 00897 draw a solid arc */ 00898 if ((da <= 0) || (db <= 0)) { 00899 o_arc_print_solid(toplevel, fp, 00900 x, y, radius, 00901 angle1, angle2, 00902 color, 00903 arc_width, length, space, origin_x, origin_y); 00904 return; 00905 } 00906 00907 fprintf(fp,"["); 00908 d = angle1; 00909 while ((d + da + db) < (angle1 + angle2)) { 00910 a1 = d; 00911 d = d + da; 00912 00913 fprintf(fp,"[%d %d] ", 00914 a1, a1+da); 00915 00916 d = d + db; 00917 } 00924 if ((d + da) < (angle1 + angle2)) { 00925 a1 = d; 00926 } else { 00927 a1 = d; 00928 } 00929 00930 fprintf(fp,"[%d %d] ", 00931 a1, a1+da); 00932 00933 00934 fprintf(fp,"] %d %d %d %d dashedarc %% dashed\n", 00935 x,y, radius, arc_width); 00936 00937 } 00938 00967 void o_arc_print_center(TOPLEVEL *toplevel, FILE *fp, 00968 int x, int y, int radius, 00969 int angle1, int angle2, 00970 int color, 00971 int arc_width, int length, int space, 00972 int origin_x, int origin_y) 00973 { 00974 int da, db, a1, d; 00975 00976 f_print_set_color(toplevel, fp, color); 00977 00992 /* Inverting angle2 if < 0 and changing angle1 accordingly */ 00993 /* the loop test assume that da > 0 */ 00994 if (angle2 < 0) { 00995 angle1 = angle1 + angle2; 00996 angle2 = -angle2; 00997 } 00998 00999 da = (int) ((length * 180) / (M_PI * ((double) radius))); 01000 db = (int) ((space * 180) / (M_PI * ((double) radius))); 01001 01002 /* If da or db too small to be displayed, draw an arc */ 01003 if ((da <= 0) || (db <= 0)) { 01004 o_arc_print_solid(toplevel, fp, 01005 x, y, radius, 01006 angle1, angle2, 01007 color, 01008 arc_width, length, space, origin_x, origin_y); 01009 return; 01010 } 01011 01012 fprintf(fp, "["); 01013 d = angle1; 01014 while ((d + da + 2 * db) < (angle1 + angle2)) { 01015 a1 = d; 01016 d = d + da; 01017 fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da); 01018 01019 d = d + db; 01020 /* 01021 xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180)); 01022 ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180)); 01023 */ 01024 fprintf(fp,"[%d] ",d); 01025 d = d + db; 01026 } 01036 if ((d + da) < (angle1 + angle2)) { 01037 a1 = d; 01038 01039 d = d + da; 01040 } else { 01041 a1 = d; 01042 01043 d = d + da; 01044 } 01045 01046 fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da); 01047 01048 01049 if ((d + db) < (angle1 + angle2)) { 01050 /* 01051 xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180)); 01052 ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180)); 01053 */ 01054 fprintf(fp,"[%d] ",d); 01055 01056 } 01057 01058 fprintf(fp,"] %d %d %d %d dashedarc %% center\n", 01059 x,y, radius, arc_width); 01060 } 01061 01095 void o_arc_print_phantom(TOPLEVEL *toplevel, FILE *fp, 01096 int x, int y, int radius, 01097 int angle1, int angle2, 01098 int color, 01099 int arc_width, int length, int space, 01100 int origin_x, int origin_y) 01101 { 01102 int da, db, a1, d; 01103 01104 f_print_set_color(toplevel, fp, color); 01105 01120 /* Inverting angle2 if < 0 and changing angle1 accordingly */ 01121 /* the loop test assume that da > 0 */ 01122 if (angle2 < 0) { 01123 angle1 = angle1 + angle2; 01124 angle2 = -angle2; 01125 } 01126 da = (int) ((length * 180) / (((double) radius) * M_PI)); 01127 db = (int) ((space * 180) / (((double) radius) * M_PI)); 01128 01129 /* If da or db too small for arc to be displayed as dotted, 01130 draw a solid arc */ 01131 if ((da <= 0) || (db <= 0)) { 01132 o_arc_print_solid(toplevel, fp, 01133 x, y, radius, 01134 angle1, angle2, 01135 color, 01136 arc_width, length, space, origin_x, origin_y); 01137 return; 01138 } 01139 01140 fprintf(fp,"["); 01141 01142 d = angle1; 01143 while ((d + da + 3 * db) < (angle1 + angle2)) { 01144 a1 = d; 01145 d = d + da; 01146 01147 fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da); 01148 01149 d = d + db; 01150 /* 01151 xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180)); 01152 ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180)); 01153 */ 01154 fprintf(fp,"[%d] ",d); 01155 01156 d = d + db; 01157 01158 /* 01159 xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180)); 01160 ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180)); 01161 */ 01162 fprintf(fp,"[%d] ",d); 01163 01164 d = d + db; 01165 } 01166 01178 if ((d + da) < (angle1 + angle2)) { 01179 a1 = d; 01180 d = d + da; 01181 } else { 01182 a1 = d; 01183 d = d + da; 01184 } 01185 01186 fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da); 01187 01188 if ((d + db) < (angle1 + angle2)) { 01189 d = d + db; 01190 01191 /* 01192 xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180)); 01193 ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180)); 01194 */ 01195 fprintf(fp,"[%d] ",d); 01196 01197 } 01198 01199 if ((d + db) < (angle1 + angle2)) { 01200 d = d + db; 01201 01202 /* 01203 xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180)); 01204 ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180)); 01205 */ 01206 01207 fprintf(fp,"[%d] ",d); 01208 01209 01210 } 01211 01212 fprintf(fp,"] %d %d %d %d dashedarc %% phantom\n", 01213 x,y, radius, arc_width); 01214 } 01215 01226 double o_arc_shortest_distance (OBJECT *object, int x, int y, int force_solid) 01227 { 01228 double shortest_distance; 01229 double radius; 01230 01231 g_return_val_if_fail (object->arc != NULL, G_MAXDOUBLE); 01232 01233 radius = ((double)object->arc->width) / 2.0; 01234 01235 if (o_arc_within_sweep (object->arc, x, y)) { 01236 double distance_to_center; 01237 double dx; 01238 double dy; 01239 01240 dx = ((double)x) - ((double)object->arc->x); 01241 dy = ((double)y) - ((double)object->arc->y); 01242 01243 distance_to_center = sqrt ((dx * dx) + (dy * dy)); 01244 01245 shortest_distance = fabs (distance_to_center - radius); 01246 01247 } else { 01248 double angle; 01249 double distance_to_end0; 01250 double distance_to_end1; 01251 double dx, dy; 01252 01253 angle = G_PI * ((double)object->arc->start_angle) / 180; 01254 01255 dx = ((double)x) - radius * cos (angle) - ((double)object->arc->x); 01256 dy = ((double)y) - radius * sin (angle) - ((double)object->arc->y); 01257 01258 distance_to_end0 = sqrt ((dx * dx) + (dy * dy)); 01259 01260 angle += G_PI * ((double)object->arc->end_angle) / 180; 01261 01262 dx = ((double)x) - radius * cos (angle) - ((double)object->arc->x); 01263 dy = ((double)y) - radius * sin (angle) - ((double)object->arc->y); 01264 01265 distance_to_end1 = sqrt ((dx * dx) + (dy * dy)); 01266 01267 shortest_distance = min (distance_to_end0, distance_to_end1); 01268 } 01269 01270 return shortest_distance; 01271 } 01272 01282 gboolean o_arc_within_sweep(ARC *arc, gint x, gint y) 01283 { 01284 gdouble a0; 01285 gdouble a1; 01286 gdouble angle; 01287 gdouble dx; 01288 gdouble dy; 01289 01290 if (arc == NULL) { 01291 g_critical("o_arc_within_sweep(): arc == NULL\n"); 01292 return FALSE; 01293 } 01294 01295 dx = ((gdouble) x) - ((gdouble) arc->x); 01296 dy = ((gdouble) y) - ((gdouble) arc->y); 01297 01298 angle = 180 * atan2(dy, dx) / G_PI; 01299 01300 if (arc->end_angle > 0) { 01301 a0 = arc->start_angle; 01302 a1 = arc->start_angle + arc->end_angle; 01303 } else { 01304 a0 = arc->start_angle + arc->end_angle + 360; 01305 a1 = arc->start_angle + 360; 01306 } 01307 01308 while (angle < a0) { 01309 angle+=360; 01310 } 01311 01312 return (angle < a1); 01313 } 01314