Ejemplo n.º 1
0
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);
  }
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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];
}