static real arc_distance_from(Arc *arc, Point *point) { Point *endpoints; Point from_center; real angle; real d, d2; endpoints = &arc->connection.endpoints[0]; from_center = *point; point_sub(&from_center, &arc->center); angle = -atan2(from_center.y, from_center.x)*180.0/M_PI; if (angle<0) angle+=360.0; if (in_angle(angle, arc->angle1, arc->angle2)) { d = fabs(sqrt(point_dot(&from_center, &from_center)) - arc->radius); d -= arc->line_width/2.0; if (d<0) d = 0.0; return d; } else { d = distance_point_point(&endpoints[0], point); d2 = distance_point_point(&endpoints[1], point); return MIN(d,d2); } }
static void arc_update_data(Arc *arc) { Connection *conn = &arc->connection; Object *obj = (Object *) arc; Point *endpoints; real x1,y1,x2,y2,xc,yc; real lensq, alpha, radius; real angle1, angle2; endpoints = &arc->connection.endpoints[0]; x1 = endpoints[0].x; y1 = endpoints[0].y; x2 = endpoints[1].x; y2 = endpoints[1].y; lensq = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1); radius = lensq/(8*arc->curve_distance) + arc->curve_distance/2.0; alpha = (radius - arc->curve_distance) / sqrt(lensq); xc = (x1 + x2) / 2.0 + (y2 - y1)*alpha; yc = (y1 + y2) / 2.0 + (x1 - x2)*alpha; angle1 = -atan2(y1-yc, x1-xc)*180.0/M_PI; if (angle1<0) angle1+=360.0; angle2 = -atan2(y2-yc, x2-xc)*180.0/M_PI; if (angle2<0) angle2+=360.0; if (radius<0.0) { real tmp; tmp = angle1; angle1 = angle2; angle2 = tmp; radius = -radius; } arc->radius = radius; arc->center.x = xc; arc->center.y = yc; arc->angle1 = angle1; arc->angle2 = angle2; connection_update_boundingbox(conn); /* fix boundingbox for line_width: */ if (in_angle(0, arc->angle1, arc->angle2)) { obj->bounding_box.right = arc->center.x + arc->radius; } if (in_angle(90, arc->angle1, arc->angle2)) { obj->bounding_box.top = arc->center.y - arc->radius; } if (in_angle(180, arc->angle1, arc->angle2)) { obj->bounding_box.left = arc->center.x - arc->radius; } if (in_angle(270, arc->angle1, arc->angle2)) { obj->bounding_box.bottom = arc->center.y + arc->radius; } /* Fix boundingbox for arrowheads */ if (arc->start_arrow.type != ARROW_NONE || arc->end_arrow.type != ARROW_NONE) { real arrow_width = 0.0; if (arc->start_arrow.type != ARROW_NONE) arrow_width = arc->start_arrow.width; if (arc->end_arrow.type != ARROW_NONE) arrow_width = MAX(arrow_width, arc->start_arrow.width); obj->bounding_box.top -= arrow_width; obj->bounding_box.left -= arrow_width; obj->bounding_box.bottom += arrow_width; obj->bounding_box.right += arrow_width; } obj->bounding_box.top -= arc->line_width/2; obj->bounding_box.left -= arc->line_width/2; obj->bounding_box.bottom += arc->line_width/2; obj->bounding_box.right += arc->line_width/2; obj->position = conn->endpoints[0]; arc_update_handles(arc); }
static void arc_update_data(Arc *arc) { Connection *conn = &arc->connection; LineBBExtras *extra =&conn->extra_spacing; DiaObject *obj = &conn->object; Point *endpoints; real x1,y1,x2,y2,xc,yc; real lensq, alpha, radius; real angle1, angle2; gboolean righthand; endpoints = &arc->connection.endpoints[0]; x1 = endpoints[0].x; y1 = endpoints[0].y; x2 = endpoints[1].x; y2 = endpoints[1].y; lensq = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1); if (fabs(arc->curve_distance) > 0.01) radius = lensq/(8*arc->curve_distance) + arc->curve_distance/2.0; else radius = 0.0; /* not really but used for bbox calculation below */ if (lensq == 0.0 || arc_is_line (arc)) alpha = 1.0; /* arbitrary, but /not/ 1/0 */ else alpha = (radius - arc->curve_distance) / sqrt(lensq); xc = (x1 + x2) / 2.0 + (y2 - y1)*alpha; yc = (y1 + y2) / 2.0 + (x1 - x2)*alpha; angle1 = -atan2(y1-yc, x1-xc)*180.0/M_PI; if (angle1<0) angle1+=360.0; angle2 = -atan2(y2-yc, x2-xc)*180.0/M_PI; if (angle2<0) angle2+=360.0; if (radius<0.0) { real tmp; tmp = angle1; angle1 = angle2; angle2 = tmp; radius = -radius; } arc->radius = radius; arc->center.x = xc; arc->center.y = yc; arc->angle1 = angle1; arc->angle2 = angle2; /* LineBBExtras not applicable to calculate the arrows bounding box */ extra->start_trans = extra->end_trans = extra->start_long = extra->end_long = (arc->line_width / 2.0); /* updates midpoint */ arc_update_handles(arc); /* startpoint, midpoint, endpoint */ righthand = is_right_hand (&endpoints[0], &arc->middle_handle.pos, &endpoints[1]); connection_update_boundingbox(conn); /* fix boundingbox for arc's special shape XXX find a more elegant way: */ if (in_angle(0, arc->angle1, arc->angle2)) { /* rigth side, y does not matter if included */ Point pt = { arc->center.x + arc->radius + (arc->line_width / 2.0), y1 }; rectangle_add_point (&obj->bounding_box, &pt); } if (in_angle(90, arc->angle1, arc->angle2)) { /* top side, x does not matter if included */ Point pt = {x1, arc->center.y - arc->radius - (arc->line_width / 2.0) }; rectangle_add_point (&obj->bounding_box, &pt); } if (in_angle(180, arc->angle1, arc->angle2)) { /* left side, y does not matter if included */ Point pt = { arc->center.x - arc->radius - (arc->line_width / 2.0), y1 }; rectangle_add_point (&obj->bounding_box, &pt); } if (in_angle(270, arc->angle1, arc->angle2)) { /* bootom side, x does not matter if included */ Point pt = { x1, arc->center.y + arc->radius + (arc->line_width / 2.0) }; rectangle_add_point (&obj->bounding_box, &pt); } if (arc->start_arrow.type != ARROW_NONE) { /* a good from-point would be the chord of arrow length, but draw_arc_with_arrows currently uses the tangent * For big arcs the difference is not huge and the minimum size of small arcs should be limited by the arror length. */ Rectangle bbox = {0,}; real tmp; Point move_arrow, move_line; Point to = arc->connection.endpoints[0]; Point from = to; point_sub (&from, &arc->center); tmp = from.x; if (righthand) from.x = -from.y, from.y = tmp; else from.x = from.y, from.y = -tmp; point_add (&from, &to); calculate_arrow_point(&arc->start_arrow, &to, &from, &move_arrow, &move_line, arc->line_width); /* move them */ point_sub(&to, &move_arrow); point_sub(&from, &move_line); arrow_bbox(&arc->start_arrow, arc->line_width, &to, &from, &bbox); rectangle_union(&obj->bounding_box, &bbox); } if (arc->end_arrow.type != ARROW_NONE) { Rectangle bbox = {0,}; real tmp; Point move_arrow, move_line; Point to = arc->connection.endpoints[1]; Point from = to; point_sub (&from, &arc->center); tmp = from.x; if (righthand) from.x = from.y, from.y = -tmp; else from.x = -from.y, from.y = tmp; point_add (&from, &to); calculate_arrow_point(&arc->end_arrow, &to, &from, &move_arrow, &move_line, arc->line_width); /* move them */ point_sub(&to, &move_arrow); point_sub(&from, &move_line); arrow_bbox(&arc->end_arrow, arc->line_width, &to, &from, &bbox); rectangle_union(&obj->bounding_box, &bbox); } /* if selected put the centerpoint in the box, too. */ obj->enclosing_box = obj->bounding_box; rectangle_add_point(&obj->enclosing_box, &arc->center); obj->position = conn->endpoints[0]; }