Beispiel #1
0
static void
beziergon_update_data(Beziergon *beziergon)
{
  BezierShape *bez = &beziergon->bezier;
  DiaObject *obj = &bez->object;
  ElementBBExtras *extra = &bez->extra_spacing;

  beziershape_update_data(bez);

  extra->border_trans = beziergon->line_width / 2.0;
  beziershape_update_boundingbox(bez);

  /* update the enclosing box using the control points */
  {
    int i, num_points = bez->bezier.num_points;
    obj->enclosing_box = obj->bounding_box;
    for (i = 0; i < num_points; ++i) {
      if (bez->bezier.points[i].type != BEZ_CURVE_TO)
        continue;
      rectangle_add_point(&obj->enclosing_box, &bez->bezier.points[i].p1);      
      rectangle_add_point(&obj->enclosing_box, &bez->bezier.points[i].p2);      
    }
  }
  obj->position = bez->bezier.points[0].p1;
}
Beispiel #2
0
void bicubicbezier2D_bbox(const Point *p0,const Point *p1,
                          const Point *p2,const Point *p3,
                          const PolyBBExtras *extra,
                          Rectangle *rect)
{
    double x[4],y[4];
    Point vl,vt,p,tt;
    double *xy;
    int i,extr;
    double u[2];

    rect->setLeft(p0->x());
    rect->setRight(p0->x());
    rect->setTop(p0->y());
    rect->setBottom(p0->y());

    rectangle_add_point(rect,p3);

    point_copy_add_scaled(&vl,p0,p1,-1);
    point_normalize(&vl);

    add_arrow_rectangle(rect,p0,&vl,extra->startLong,
            qMax(extra->startTrans, extra->middleTrans));

    point_copy_add_scaled(&vl,p3,p2,-1);
    point_normalize(&vl);

    add_arrow_rectangle(rect,p3,&vl,extra->endLong,
            qMax(extra->endTrans, extra->middleTrans));

    x[0] = p0->x(); x[1] = p1->x(); x[2] = p2->x(); x[3] = p3->x();
    y[0] = p0->y(); y[1] = p1->y(); y[2] = p2->y(); y[3] = p3->y();

    for (xy = x; xy ; xy=(xy==x?y:NULL) ) {
        extr = bicubicbezier_extrema(xy,u);
        for (i=0;i<extr;i++) {
            if ((u[i]<0) || (u[i]>1)) continue;
            p.setX(bezier_eval(x,u[i]));
            vl.setX(bezier_eval_tangent(x,u[i]));
            p.setY(bezier_eval(y,u[i]));
            vl.setY(bezier_eval_tangent(y,u[i]));
            point_normalize(&vl);
            point_get_perp(&vt,&vl);

            point_copy_add_scaled(&tt,&p,&vt,extra->middleTrans);
            rectangle_add_point(rect,&tt);
            point_copy_add_scaled(&tt,&p,&vt,-extra->middleTrans);
            rectangle_add_point(rect,&tt);
        }
    }
}
Beispiel #3
0
/** Calculate the boundingbox for a 2D bezier curve segment.
 * @param p0 start point
 * @param p1 1st control point
 * @param p2 2nd control point
 * @param p3 end point
 * @param extra information about extra space from linewidth and arrow to add to the bounding box
 * @param rect The rectangle that the segment fits inside.
 */
void
bicubicbezier2D_bbox(const Point *p0,const Point *p1,
                     const Point *p2,const Point *p3,
                     const PolyBBExtras *extra,
                     Rectangle *rect)
{
  real x[4],y[4];
  Point vl,vt,p,tt;
  real *xy;
  int i,extr;
  real u[2];

  rect->left = rect->right = p0->x;
  rect->top = rect->bottom = p0->y;

  rectangle_add_point(rect,p3);
  /* start point */  
  point_copy_add_scaled(&vl,p0,p1,-1);
  point_normalize(&vl); 
  add_arrow_rectangle(rect,p0,&vl,extra->start_long,MAX(extra->start_trans,
                                                         extra->middle_trans));

  /* end point */
  point_copy_add_scaled(&vl,p3,p2,-1);
  point_normalize(&vl); 
  add_arrow_rectangle(rect,p3,&vl,extra->end_long,MAX(extra->end_trans,
                                                      extra->middle_trans));

  /* middle part */  
  x[0] = p0->x; x[1] = p1->x; x[2] = p2->x; x[3] = p3->x;
  y[0] = p0->y; y[1] = p1->y; y[2] = p2->y; y[3] = p3->y;

  for (xy = x; xy ; xy=(xy==x?y:NULL) ) { /* sorry */
    extr = bicubicbezier_extrema(xy,u);
    for (i=0;i<extr;i++) {
      if ((u[i]<0) || (u[i]>1)) continue;
      p.x = bezier_eval(x,u[i]);
      vl.x = bezier_eval_tangent(x,u[i]);
      p.y = bezier_eval(y,u[i]);
      vl.y = bezier_eval_tangent(y,u[i]);
      point_normalize(&vl);
      point_get_perp(&vt,&vl);

      point_copy_add_scaled(&tt,&p,&vt,extra->middle_trans);
      rectangle_add_point(rect,&tt);
      point_copy_add_scaled(&tt,&p,&vt,-extra->middle_trans);
      rectangle_add_point(rect,&tt);
    }
  }
}
Beispiel #4
0
Datei: link.c Projekt: UIKit0/dia
static void
link_update_data(Link *link)
{
  Connection *conn = &link->connection;
  DiaObject *obj = &conn->object;
  Rectangle rect;
  Point p1,p2,p3,p4,pa;

/* Too complex to easily decide */
/*
  if (connpoint_is_autogap(conn->endpoint_handles[0].connected_to) ||
      connpoint_is_autogap(conn->endpoint_handles[1].connected_to)) {
    connection_adjust_for_autogap(conn);
  }
*/
  obj->position = conn->endpoints[0];

  link->pm_handle.pos = link->pm;

  connection_update_handles(conn);
  connection_update_boundingbox(conn);

  /* endpoint */
  p1 = conn->endpoints[0];
  p2 = conn->endpoints[1];

  /* bezier */
  compute_line(&p1,&p2,&link->pm,link->line);

  /* connection point */
  link->connector.pos.x=p1.x;
  link->connector.pos.y=p1.y;

  /* Update boundingbox for mid-point (TBD is this necessary ?) */
  rectangle_add_point(&obj->bounding_box, &link->pm);

  /* Add boundingbox for annotation text (over-estimated) : */
  pa=compute_annot(&p1,&p2,&link->pm,0.75,0.75);
  rect.left = pa.x-0.3;
  rect.right = rect.left+0.6;
  rect.top = pa.y - LINK_FONTHEIGHT;
  rect.bottom = rect.top + 2*LINK_FONTHEIGHT;
  rectangle_union(&obj->bounding_box, &rect);

  /* Add boundingbox for dependency decoration (with some overestimation toi be safe) */
  pa=bezier_line_eval(link->line,2,0.25);
  p3.x=pa.x-LINK_DEP_WIDTH*1.5;
  p3.y=pa.y-LINK_DEP_HEIGHT*1.5;
  p4.x=p3.x+LINK_DEP_WIDTH*3;
  p4.y=p3.y+LINK_DEP_HEIGHT*3;
  rect.left=p3.x;
  rect.right=p4.x;
  rect.top=p3.y;
  rect.bottom=p4.y;
  rectangle_union(&obj->bounding_box, &rect);
}
Beispiel #5
0
void add_arrow_rectangle(Rectangle *rect,
                                const Point *vertex,
                                const Point *normed_dir,
                                double extra_long,double extra_trans)
{
    Point vl,vt,pt;
    vl = *normed_dir;

    point_get_perp(&vt,&vl);
    point_copy_add_scaled(&pt,vertex,&vl,extra_long);
    point_add_scaled(&pt,&vt,extra_trans);
    rectangle_add_point(rect,&pt);
    point_add_scaled(&pt,&vt,-2.0 * extra_trans);
    rectangle_add_point(rect,&pt);
    point_add_scaled(&pt,&vl,-2.0 * extra_long);
    rectangle_add_point(rect,&pt);
    point_add_scaled(&pt,&vt,2.0 * extra_trans);
    rectangle_add_point(rect,&pt);
}
Beispiel #6
0
static void
textobj_update_data(Textobj *textobj)
{
  Point to2;
  DiaObject *obj = &textobj->object;
  Rectangle tx_bb;

  text_set_position(textobj->text, &obj->position);
  text_calc_boundingbox(textobj->text, &obj->bounding_box);

  to2 = obj->position;
  textobj_valign_point(textobj, &to2);
  /* shift text position depending on text alignment */
  if (VALIGN_TOP == textobj->vert_align)
    to2.y += textobj->margin; /* down */
  else if (VALIGN_BOTTOM == textobj->vert_align)
    to2.y -= textobj->margin; /* up */
  if (ALIGN_LEFT == textobj->text->alignment)
    to2.x += textobj->margin; /* right */
  else if (ALIGN_RIGHT == textobj->text->alignment)
    to2.x -= textobj->margin; /* left */
  text_set_position(textobj->text, &to2);

  /* always use the unrotated box ... */
  text_calc_boundingbox(textobj->text, &tx_bb);
  /* grow the bounding box by 2x margin */
  obj->bounding_box.top    -= textobj->margin;
  obj->bounding_box.left   -= textobj->margin;
  obj->bounding_box.bottom += textobj->margin;
  obj->bounding_box.right  += textobj->margin;

  textobj->text_handle.pos = obj->position;
  if (textobj->text_angle == 0) {
    obj->bounding_box = tx_bb;
    g_return_if_fail (obj->enclosing_box != NULL);
    *obj->enclosing_box = tx_bb;
  } else {
    /* ... and grow it when necessary */
    Point poly[4];
    int i;

    _textobj_get_poly (textobj, poly);
    /* we don't want the joined box for boundingbox because
     * selection would become too greedy than.
     */
    obj->bounding_box.left = obj->bounding_box.right = poly[0].x;
    obj->bounding_box.top = obj->bounding_box.bottom = poly[0].y;
    for (i = 1; i < 4; ++i)
      rectangle_add_point (&obj->bounding_box, &poly[i]);
    g_return_if_fail (obj->enclosing_box != NULL);
    *obj->enclosing_box = obj->bounding_box;
    /* join for editing/selection bbox */
    rectangle_union (obj->enclosing_box, &tx_bb);
  }
}
Beispiel #7
0
/** Calculate the bounding box for a simple line.
 * @param p1 One end of the line.
 * @param p2 The other end of the line.
 * @param extra Extra information 
 * @param rect The box that the line and extra stuff fits inside.
 */
void
line_bbox(const Point *p1, const Point *p2,
          const LineBBExtras *extra,
          Rectangle *rect)
{
  Point vl;
  
  rect->left = rect->right = p1->x;
  rect->top = rect->bottom = p1->y;

  rectangle_add_point(rect,p2); /* as a safety, so we don't need to care if it above or below p1 */
  
  point_copy_add_scaled(&vl,p1,p2,-1);
  point_normalize(&vl);
  add_arrow_rectangle(rect,p1,&vl,extra->start_long,extra->start_trans);
  point_scale(&vl,-1);
  add_arrow_rectangle(rect,p2,&vl,extra->end_long,extra->end_trans);
}
Beispiel #8
0
void line_bbox(const Point *p1, const Point *p2,
        const LineBBExtras *extra,
        Rectangle *rect)
{
    Point vl;

    rect->setLeft(p1->x());
    rect->setRight(p1->x());
    rect->setTop(p1->y());
    rect->setBottom(p1->y());

    rectangle_add_point(rect,p2);

    point_copy_add_scaled(&vl,p1,p2,-1);
    point_normalize(&vl);
    add_arrow_rectangle(rect,p1,&vl,extra->startLong,extra->startTrans);
    point_scale(&vl,-1);
    add_arrow_rectangle(rect,p2,&vl,extra->endLong,extra->endTrans);
}
Beispiel #9
0
static void
bus_update_data(Bus *bus)
{
  Connection *conn = &bus->connection;
  DiaObject *obj = &conn->object;
  int i;
  Point u, v, vhat;
  Point *endpoints;
  real ulen;
  real min_par, max_par;

/*
 * This seems to break stuff wildly.
 */
/*  
  if (connpoint_is_autogap(conn->endpoint_handles[0].connected_to) ||
      connpoint_is_autogap(conn->endpoint_handles[1].connected_to)) {
    connection_adjust_for_autogap(conn);
  }
*/
  endpoints = &conn->endpoints[0]; 
  obj->position = endpoints[0];

  v = endpoints[1];
  point_sub(&v, &endpoints[0]);
  if ((fabs(v.x) == 0.0) && (fabs(v.y)==0.0)) {
    v.x += 0.01;
  }
  vhat = v;
  point_normalize(&vhat);
  min_par = 0.0;
  max_par = point_dot(&vhat, &v);
  for (i=0;i<bus->num_handles;i++) {
    u = bus->handles[i]->pos;
    point_sub(&u, &endpoints[0]);
    ulen = point_dot(&u, &vhat);
    min_par = MIN(min_par, ulen);
    max_par = MAX(max_par, ulen);
    bus->parallel_points[i] = vhat;
    point_scale(&bus->parallel_points[i], ulen);
    point_add(&bus->parallel_points[i], &endpoints[0]);
  }
  
  min_par -= LINE_WIDTH/2.0;
  max_par += LINE_WIDTH/2.0;

  bus->real_ends[0] = vhat;
  point_scale(&bus->real_ends[0], min_par);
  point_add(&bus->real_ends[0], &endpoints[0]);
  bus->real_ends[1] = vhat;
  point_scale(&bus->real_ends[1], max_par);
  point_add(&bus->real_ends[1], &endpoints[0]);

  connection_update_boundingbox(conn);
  rectangle_add_point(&obj->bounding_box, &bus->real_ends[0]);
  rectangle_add_point(&obj->bounding_box, &bus->real_ends[1]);
  for (i=0;i<bus->num_handles;i++) {
    rectangle_add_point(&obj->bounding_box, &bus->handles[i]->pos);
  }

  connection_update_handles(conn);
}
Beispiel #10
0
static void
step_update_data(Step *step)
{
  Element *elem = &step->element;
  DiaObject *obj = &elem->object;
  ElementBBExtras *extra = &elem->extra_spacing;
  Point *p,ulc;

  ulc = elem->corner;
  ulc.x += ((STEP_DECLAREDWIDTH - STEP_WIDTH) / 2.0); /* we cheat a little */

  step->A.x = 0.0 + (STEP_WIDTH / 2.0); step->A.y = 0.0;
  step->D.x = 0.0 + (STEP_WIDTH / 2.0); step->D.y = 0.0 + STEP_HEIGHT;

  step->E.x = 0.0; step->E.y = 0.5;
  step->F.x = STEP_WIDTH; step->F.y = STEP_HEIGHT- 0.5;

  
  switch(step->type) {
  case STEP_INITIAL:
    step->I.x = step->E.x - 2 * STEP_LINE_WIDTH; 
    step->I.y = step->E.y - 2 * STEP_LINE_WIDTH;
    step->J.x = step->F.x + 2 * STEP_LINE_WIDTH; 
    step->J.y = step->F.y + 2 * STEP_LINE_WIDTH;

    step->B.x = step->A.x; step->B.y = step->I.y;
    step->C.x = step->D.x; step->C.y = step->J.y;
    step->Z.x = step->J.x; step->Z.y = STEP_HEIGHT / 2;
    break;
  case STEP_MACROCALL:
    step->I.x = step->E.x; 
    step->I.y = step->E.y - 2 * STEP_LINE_WIDTH;
    step->J.x = step->F.x; 
    step->J.y = step->F.y + 2 * STEP_LINE_WIDTH;

    step->B.x = step->A.x; step->B.y = step->I.y;
    step->C.x = step->D.x; step->C.y = step->J.y;
    step->Z.x = step->J.x; step->Z.y = STEP_HEIGHT / 2;
    break;
  case STEP_SUBPCALL:
    step->I.x = step->E.x - 2 * STEP_LINE_WIDTH; 
    step->I.y = step->E.y;
    step->J.x = step->F.x + 2 * STEP_LINE_WIDTH; 
    step->J.y = step->F.y;

    step->B.x = step->A.x; step->B.y = step->I.y;
    step->C.x = step->D.x; step->C.y = step->J.y;
    step->Z.x = step->J.x; step->Z.y = STEP_HEIGHT / 2;
    break;
  default: /* regular or macro end steps */
    step->B.x = step->A.x; step->B.y = step->E.y;
    step->C.x = step->D.x; step->C.y = step->F.y;
    step->Z.x = step->F.x; step->Z.y = STEP_HEIGHT / 2;
  }
  
  step->G.x = step->A.x;
  step->G.y = (STEP_HEIGHT / 2)  + (.3 * step->font_size);
  step->H.x = step->E.x + (1.2 * STEP_DOT_RADIUS);
  step->H.y = step->F.y - (1.2 * STEP_DOT_RADIUS);
    
  for (p=&(step->A); p<=&(step->Z) ; p++)
    point_add(p,&ulc);

  /* Update handles: */
  if (step->north.pos.x == -65536.0) {
    step->north.pos = step->A;
    step->south.pos = step->D;
  }
  step->NU1.x = step->north.pos.x;
  step->NU2.x = step->A.x;
  step->NU1.y = step->NU2.y = (step->north.pos.y + step->A.y) / 2.0;
  step->SD1.x = step->D.x;
  step->SD2.x = step->south.pos.x;
  step->SD1.y = step->SD2.y = (step->south.pos.y + step->D.y) / 2.0;

  /* Update connections: */
  step->connections[0].pos = step->A;
  step->connections[0].directions = DIR_NORTH;
  step->connections[1].pos = step->D;
  step->connections[1].directions = DIR_SOUTH;
  step->connections[2].pos = step->Z;
  step->connections[2].directions = DIR_EAST;
  step->connections[3].pos = step->H;
  step->connections[3].directions = DIR_WEST;

  /* recalc the bounding box : */
  if ((step->type == STEP_INITIAL) || (step->type == STEP_SUBPCALL)) {
    extra->border_trans = 2.5 * STEP_LINE_WIDTH;
  } else {
    extra->border_trans = STEP_LINE_WIDTH / 2;
  }
  
  element_update_boundingbox(elem);
  rectangle_add_point(&obj->bounding_box,&step->north.pos);
  rectangle_add_point(&obj->bounding_box,&step->south.pos);

  obj->position = elem->corner;
  
  element_update_handles(elem);
}
Beispiel #11
0
void polybezier_bbox(const BezPoint *pts, int numpoints,
                     const PolyBBExtras *extra, bool closed,
                     Rectangle *rect)
{
    Point vx,vp,vn,vsc;
    int i,prev,next;
    Rectangle rt;
    PolyBBExtras bextra,start_bextra,end_bextra;
    LineBBExtras lextra,start_lextra,end_lextra,full_lextra;
    bool start,end;

    rect->setLeft(pts[0].p1.x());
    rect->setRight(pts[0].p1.x());

    rect->setTop(pts[0].p1.y());
    rect->setBottom(pts[0].p1.y());

    if (!closed) {
        start_lextra.startLong = extra->startLong;
        start_lextra.startTrans = qMax(extra->startTrans,extra->middleTrans);
        start_lextra.endLong = 0;
        start_lextra.endTrans = extra->middleTrans;

        end_lextra.startLong = 0;
        end_lextra.startTrans = extra->middleTrans;
        end_lextra.endLong = extra->endLong;
        end_lextra.endTrans = qMax(extra->endTrans,extra->middleTrans);
    }

    full_lextra.startLong = extra->startLong;
    full_lextra.startTrans = qMax(extra->startTrans,extra->middleTrans);
    full_lextra.endLong = extra->endLong;
    full_lextra.endTrans = qMax(extra->endTrans,extra->middleTrans);

    if (!closed) {
        lextra.startLong = 0;
        lextra.startTrans = extra->middleTrans;
        lextra.endLong = 0;
        lextra.endTrans = extra->middleTrans;

        start_bextra.startLong = extra->startLong;
        start_bextra.startTrans = extra->startTrans;
        start_bextra.middleTrans = extra->middleTrans;
        start_bextra.endLong = 0;
        start_bextra.endTrans = extra->middleTrans;

        end_bextra.startLong = 0;
        end_bextra.startTrans = extra->middleTrans;
        end_bextra.middleTrans = extra->middleTrans;
        end_bextra.endLong = extra->endLong;
        end_bextra.endTrans = extra->endTrans;
    }

    bextra.startLong = 0;
    bextra.startTrans = extra->middleTrans;
    bextra.middleTrans = extra->middleTrans;
    bextra.endLong = 0;
    bextra.endTrans = extra->middleTrans;


    for (i=1;i<numpoints;i++) {
        next = (i+1) % numpoints;
        prev = (i-1) % numpoints;
        if (closed && (next == 0)) next=1;
        if (closed && (prev == 0)) prev=numpoints-1;

        if (pts[i].type == BezPoint::BEZ_MOVE_TO) {
            continue;
        }

        switch(pts[i].type) {
            case BezPoint::BEZ_MOVE_TO:
                break;
            case BezPoint::BEZ_LINE_TO:
                vx = pts[i].p1;
                switch(pts[prev].type) {
                    case BezPoint::BEZ_MOVE_TO:
                    case BezPoint::BEZ_LINE_TO:
                        vsc = pts[prev].p1;
                        vp = pts[prev].p1;
                        break;
                    case BezPoint::BEZ_CURVE_TO:
                        vsc = pts[prev].p3;
                        vp = pts[prev].p3;
                        break;
                }
                break;
            case BezPoint::BEZ_CURVE_TO:
                vx = pts[i].p3;
                vp = pts[i].p2;
                switch(pts[prev].type) {
                    case BezPoint::BEZ_MOVE_TO:
                    case BezPoint::BEZ_LINE_TO:
                        vsc = pts[prev].p1;
                        break;
                    case BezPoint::BEZ_CURVE_TO:
                        vsc = pts[prev].p3;
                        break;
                }

                break;
        }
        start = (pts[prev].type == BezPoint::BEZ_MOVE_TO);
        end = (pts[next].type == BezPoint::BEZ_MOVE_TO);
        vn = pts[next].p1;

        if (closed) {
            if (pts[i].type == BezPoint::BEZ_LINE_TO) {
                line_bbox(&vsc,&vx,&full_lextra,&rt);
            } else {
                bicubicbezier2D_bbox(&vsc,
                        &pts[i].p1,&pts[i].p2,&pts[i].p3,
                        &bextra,
                        &rt);
            }
        } else if (start) {
            if (pts[i].type == BezPoint::BEZ_LINE_TO) {
                if (end) {
                    line_bbox(&vsc,&vx,&full_lextra,&rt);
                } else {
                    line_bbox(&vsc,&vx,&start_lextra,&rt);
                }
            } else {
                if (end) {
                    bicubicbezier2D_bbox(&vsc,
                            &pts[i].p1,&pts[i].p2,&pts[i].p3,
                            extra,
                            &rt);
                } else {
                    bicubicbezier2D_bbox(&vsc,
                            &pts[i].p1,&pts[i].p2,&pts[i].p3,
                            &start_bextra,
                            &rt);
                }
            }
        } else if (end) {
            if (pts[i].type == BezPoint::BEZ_LINE_TO) {
                line_bbox(&vsc,&vx,&end_lextra,&rt);
            } else {
                bicubicbezier2D_bbox(&vsc,
                        &pts[i].p1,&pts[i].p2,&pts[i].p3,
                        &end_bextra,
                        &rt);
            }
        } else {
            if (pts[i].type == BezPoint::BEZ_LINE_TO) {
                line_bbox(&vsc,&vx,&lextra,&rt);
            } else {
                bicubicbezier2D_bbox(&vsc,
                        &pts[i].p1,&pts[i].p2,&pts[i].p3,
                        &bextra,
                        &rt);
            }
        }
        *rect = rect->united(rt);

        if ((!start) && (!end)) {
            Point vpx,vxn;
            double co,alpha;

            point_copy_add_scaled(&vpx,&vx,&vp,-1);
            point_normalize(&vpx);
            point_copy_add_scaled(&vxn,&vn,&vx,-1);
            point_normalize(&vxn);

            co = point_dot(&vpx,&vxn);
            alpha = acos(-co);
            if ((co > -0.9816) && (finite(alpha))) {
                double overshoot = extra->middleTrans / sin(alpha/2.0);
                Point vovs,pto;

                point_copy_add_scaled(&vovs,&vpx,&vxn,-1);
                point_normalize(&vovs);
                point_copy_add_scaled(&pto,&vx,&vovs,overshoot);

                rectangle_add_point(rect,&pto);
            } else {
                Point vpxt,vxnt,tmp;

                point_get_perp(&vpxt,&vpx);
                point_get_perp(&vxnt,&vxn);

                point_copy_add_scaled(&tmp,&vx,&vpxt,1);
                rectangle_add_point(rect,&tmp);
                point_copy_add_scaled(&tmp,&vx,&vpxt,-1);
                rectangle_add_point(rect,&tmp);
                point_copy_add_scaled(&tmp,&vx,&vxnt,1);
                rectangle_add_point(rect,&tmp);
                point_copy_add_scaled(&tmp,&vx,&vxnt,-1);
                rectangle_add_point(rect,&tmp);
            }
        }
    }
}
Beispiel #12
0
static void
association_update_data_end(Association *assoc, int endnum)
{
  OrthConn *orth = &assoc->orth;
  DiaObject *obj = &orth->object;
  Point *points  = orth->points;
  Rectangle rect;
  AssociationEnd *end;
  Orientation dir;
  int n = orth->numpoints - 1, fp, sp;
  Point dir_poly[3];

  /* Find the first and second points depending on which end: */
  if (endnum) {
      fp = n;
      sp = n-1;
      dir = assoc->orth.orientation[n-1];
  } else {
      fp = 0;
      sp = 1;
      dir = assoc->orth.orientation[0];
  }

  /* If the points are the same, find a better candidate: */
  if (points[fp].x == points[sp].x && points[fp].y == points[sp].y) {
      sp += (endnum ? -1 : 1);
      if (sp < 0)
	  sp = 0;
      if (sp > n)
	  sp = n;
      if (points[fp].y != points[sp].y)
	  dir = VERTICAL;
      else      
	  dir = HORIZONTAL;
  }

  /* Update the text-points of the ends: */
  end = &assoc->end[endnum];
  end->text_pos = points[fp];
  switch (dir) {
  case HORIZONTAL:
    end->text_pos.y -= end->role_descent;
    if (points[fp].x < points[sp].x) {
      end->text_align = ALIGN_LEFT;
      end->text_pos.x += (get_aggregate_pos_diff(end) + ASSOCIATION_END_SPACE);
    } else {
      end->text_align = ALIGN_RIGHT;    
      end->text_pos.x -= (get_aggregate_pos_diff(end) + ASSOCIATION_END_SPACE);
    }
    break;
  case VERTICAL:
    if (end->arrow || end->aggregate != AGGREGATE_NONE)
	end->text_pos.x += ASSOCIATION_DIAMONDWIDTH / 2;
    end->text_pos.x += ASSOCIATION_END_SPACE;

    end->text_pos.y += end->role_ascent;
    if (points[fp].y > points[sp].y) {
      if (end->role!=NULL && *end->role)
          end->text_pos.y -= ASSOCIATION_FONTHEIGHT;
      if (end->multiplicity!=NULL)
          end->text_pos.y -= ASSOCIATION_FONTHEIGHT;
    }

    end->text_align = ALIGN_LEFT;
    break;
  }
  /* Add the text recangle to the bounding box: */
  rect.left = end->text_pos.x
      - (end->text_align == ALIGN_LEFT ? 0 : end->text_width);
  rect.right = rect.left + end->text_width;
  rect.top = end->text_pos.y - end->role_ascent;
  rect.bottom = rect.top + 2*ASSOCIATION_FONTHEIGHT;
  
  rectangle_union(&obj->bounding_box, &rect);
  
  if (assoc_get_direction_poly (assoc, dir_poly)) {
    int i;
    for (i = 0; i < 3; ++i)
      rectangle_add_point (&obj->bounding_box, &dir_poly[i]);
  }
}
Beispiel #13
0
static void
transition_update_data(Transition *transition)
{
  Element *elem = &transition->element;
  DiaObject *obj = &elem->object;
  Point *p;

  transition->element.extra_spacing.border_trans = TRANSITION_LINE_WIDTH / 2.0;

  obj->position = elem->corner;
  elem->width = TRANSITION_DECLAREDWIDTH;
  elem->height = TRANSITION_DECLAREDWIDTH;

  /* compute the useful points' positions : */
  transition->A.x = transition->B.x = (TRANSITION_DECLAREDWIDTH / 2.0);
  transition->A.y = (TRANSITION_DECLAREDHEIGHT / 2.0) 
    - (TRANSITION_HEIGHT / 2.0);
  transition->B.y = transition->A.y + TRANSITION_HEIGHT;
  transition->C.y = transition->D.y = (TRANSITION_DECLAREDHEIGHT / 2.0);
  transition->C.x = 
    (TRANSITION_DECLAREDWIDTH / 2.0) - (TRANSITION_WIDTH / 2.0);
  transition->D.x = transition->C.x + TRANSITION_WIDTH;
  
  transition->Z.y = (TRANSITION_DECLAREDHEIGHT / 2.0) 
    + (.3 * transition->receptivity->fontheight);

  transition->Z.x = transition->D.x + 
    dia_font_string_width("_",transition->receptivity->font,
                          transition->receptivity->fontheight);

  for (p = &transition->A; p <= &transition->Z; p++) 
    point_add(p,&elem->corner);

  transition->receptivity->pos = transition->Z;


  /* Update handles: */
  if (transition->north.pos.x == -65536.0) {
    transition->north.pos = transition->A;
    transition->south.pos = transition->B;
  }
  transition->NU1.x = transition->north.pos.x;
  transition->NU2.x = transition->A.x;
  transition->NU1.y = transition->NU2.y = 
    (transition->north.pos.y + transition->A.y) / 2.0;
  transition->SD1.x = transition->B.x;
  transition->SD2.x = transition->south.pos.x;
  transition->SD1.y = transition->SD2.y = 
    (transition->south.pos.y + transition->B.y) / 2.0;

  obj->connections[0]->pos = transition->A;
  obj->connections[0]->directions = DIR_EAST|DIR_WEST;
  obj->connections[1]->pos = transition->B;
  obj->connections[1]->directions = DIR_EAST|DIR_WEST;


  element_update_boundingbox(elem);

  rectangle_add_point(&obj->bounding_box,&transition->north.pos);
  rectangle_add_point(&obj->bounding_box,&transition->south.pos);

  /* compute the rcept's width and bounding box, then merge. */
  boolequation_calc_boundingbox(transition->receptivity,&transition->rceptbb);
  rectangle_union(&obj->bounding_box,&transition->rceptbb);

  element_update_handles(elem);
}
Beispiel #14
0
static void
bezierline_update_data(Bezierline *bezierline)
{
  BezierConn *bez = &bezierline->bez;
  DiaObject *obj = &bez->object;
  PolyBBExtras *extra = &bez->extra_spacing;

  bezierconn_update_data(bez);

  extra->start_trans = extra->start_long =
  extra->middle_trans =
  extra->end_trans = extra->end_long = (bezierline->line_width / 2.0);

  obj->position = bez->bezier.points[0].p1;

  if (connpoint_is_autogap(bez->object.handles[0]->connected_to) ||
      connpoint_is_autogap(bez->object.handles[3*(bez->bezier.num_points-1)]->connected_to) ||
      bezierline->absolute_start_gap || bezierline->absolute_end_gap ||
      bezierline->start_arrow.type != ARROW_NONE || bezierline->end_arrow.type != ARROW_NONE) {
    Point gap_points[4];
    Rectangle bbox_union = {bez->bezier.points[0].p1.x, bez->bezier.points[0].p1.y,
			    bez->bezier.points[0].p1.x, bez->bezier.points[0].p1.y};
    compute_gap_points(bezierline, gap_points);
    exchange_bez_gap_points(bez,gap_points);
    /* further modifying the points data, accounts for corrcet arrow and bezier bounding box */
    if (bezierline->start_arrow.type != ARROW_NONE) {
      Rectangle bbox;
      Point move_arrow, move_line;
      Point to = bez->bezier.points[0].p1, from = bez->bezier.points[1].p1;

      calculate_arrow_point(&bezierline->start_arrow, &to, &from, &move_arrow, &move_line, bezierline->line_width);
      point_sub(&to, &move_arrow);
      point_sub(&bez->bezier.points[0].p1, &move_line);
      arrow_bbox (&bezierline->start_arrow, bezierline->line_width, &to, &from, &bbox);
      rectangle_union (&bbox_union, &bbox);
    }
    if (bezierline->end_arrow.type != ARROW_NONE) {
      Rectangle bbox;
      Point move_arrow, move_line;
      int num_points = bez->bezier.num_points;
      Point to = bez->bezier.points[num_points-1].p3, from = bez->bezier.points[num_points-1].p2;

      calculate_arrow_point(&bezierline->end_arrow, &to, &from, &move_arrow, &move_line, bezierline->line_width);
      point_sub(&to, &move_arrow);
      point_sub(&bez->bezier.points[num_points-1].p3, &move_line);
      arrow_bbox (&bezierline->end_arrow, bezierline->line_width, &to, &from, &bbox);
      rectangle_union (&bbox_union, &bbox);
    }
    bezierconn_update_boundingbox(bez);
    rectangle_union (&obj->bounding_box, &bbox_union);
    exchange_bez_gap_points(bez,gap_points);
  } else {
    bezierconn_update_boundingbox(bez);
  }
    /* add control points to the bounding box, needed to make them visible when showing all
      * and to remove traces from them */
  {
    int i, num_points = bez->bezier.num_points;
    g_assert (obj->enclosing_box != NULL);
    *obj->enclosing_box = obj->bounding_box;
    /* starting with the second point, the first one is MOVE_TO */
    for (i = 1; i < num_points; ++i) {
      if (bez->bezier.points[i].type != BEZ_CURVE_TO)
        continue;
      rectangle_add_point(obj->enclosing_box, &bez->bezier.points[i].p1);
      rectangle_add_point(obj->enclosing_box, &bez->bezier.points[i].p2);
    }
  }
}
Beispiel #15
0
/** Calculate a bounding box for a set of bezier points.
 * @param pts The bezier points
 * @param numpoints The number of elements in `pts'
 * @param extra Extra spacing information.
 * @param closed True if the bezier points form a closed line.
 * @param rect Return value: The enclosing rectangle will be stored here.
 * @bug This function is way too long (214 lines) and should be split.
 */
void 
polybezier_bbox(const BezPoint *pts, int numpoints,
                const PolyBBExtras *extra, gboolean closed,            
                Rectangle *rect)
{
  Point vx,vn,vsc,vp;
  int i,prev,next;
  Rectangle rt;
  PolyBBExtras bextra,start_bextra,end_bextra;
  LineBBExtras lextra,start_lextra,end_lextra,full_lextra;
  gboolean start,end;

  vp.x=0;
  vp.y=0;

  g_assert(pts[0].type == BEZ_MOVE_TO);

  rect->left = rect->right = pts[0].p1.x;
  rect->top = rect->bottom = pts[0].p1.y;

  /* First, we build derived BBExtras structures, so we have something to feed 
     the primitives. */ 
  if (!closed) {
    start_lextra.start_long = extra->start_long;
    start_lextra.start_trans = MAX(extra->start_trans,extra->middle_trans);
    start_lextra.end_long = 0;
    start_lextra.end_trans = extra->middle_trans;

    end_lextra.start_long = 0;
    end_lextra.start_trans = extra->middle_trans;
    end_lextra.end_long = extra->end_long;
    end_lextra.end_trans = MAX(extra->end_trans,extra->middle_trans);
  }

  full_lextra.start_long = extra->start_long;
  full_lextra.start_trans = MAX(extra->start_trans,extra->middle_trans);
  full_lextra.end_long = extra->end_long;
  full_lextra.end_trans = MAX(extra->end_trans,extra->middle_trans);

  if (!closed) {
    lextra.start_long = 0;
    lextra.start_trans = extra->middle_trans;
    lextra.end_long = 0;
    lextra.end_trans = extra->middle_trans;

    start_bextra.start_long = extra->start_long;
    start_bextra.start_trans = extra->start_trans;
    start_bextra.middle_trans = extra->middle_trans;
    start_bextra.end_long = 0;
    start_bextra.end_trans = extra->middle_trans;

    end_bextra.start_long = 0;
    end_bextra.start_trans = extra->middle_trans;
    end_bextra.middle_trans = extra->middle_trans;
    end_bextra.end_long = extra->end_long;
    end_bextra.end_trans = extra->end_trans;
  }

  bextra.start_long = 0;
  bextra.start_trans = extra->middle_trans;
  bextra.middle_trans = extra->middle_trans;
  bextra.end_long = 0;
  bextra.end_trans = extra->middle_trans;        


  for (i=1;i<numpoints;i++) {
    next = (i+1) % numpoints;
    prev = (i-1) % numpoints;
    if (closed && (next == 0)) next=1;
    if (closed && (prev == 0)) prev=numpoints-1;

    /* We have now: 
       i = index of current vertex. 
       prev,next: index of previous/next vertices (of the control polygon) 

       We want:
        vp, vx, vn: the previous, current and next vertices;
        start, end: TRUE if we're at an end of poly (then, vp and/or vn are not
        valid, respectively).

       Some values *will* be recomputed a few times across iterations (but stored in 
       different boxes). Either gprof says it's a real problem, or gcc finally gets 
       a clue.
    */

    if (pts[i].type == BEZ_MOVE_TO) {
      continue;
    }

    switch(pts[i].type) {
    case BEZ_MOVE_TO:
      g_assert_not_reached();
      break;
    case BEZ_LINE_TO:
      point_copy(&vx,&pts[i].p1);
      switch(pts[prev].type) {
      case BEZ_MOVE_TO:
      case BEZ_LINE_TO:
        point_copy(&vsc,&pts[prev].p1);
        point_copy(&vp,&pts[prev].p1);
        break;
      case BEZ_CURVE_TO:
        point_copy(&vsc,&pts[prev].p3);
        point_copy(&vp,&pts[prev].p3);
        break;
      }
      break;
    case BEZ_CURVE_TO:
      point_copy(&vx,&pts[i].p3);
      point_copy(&vp,&pts[i].p2);
      switch(pts[prev].type) {
      case BEZ_MOVE_TO:
      case BEZ_LINE_TO:
        point_copy(&vsc,&pts[prev].p1);
        break;
      case BEZ_CURVE_TO:
        point_copy(&vsc,&pts[prev].p3);
        break;
      } /* vsc is the start of the curve. */
      
      break;
    }
    start = (pts[prev].type == BEZ_MOVE_TO);
    end = (pts[next].type == BEZ_MOVE_TO);
    point_copy(&vn,&pts[next].p1); /* whichever type pts[next] is. */

    /* Now, we know about a few vertices around the one we're dealing with.
       Depending on the shape of the (previous,current) segment, and whether 
       it's a middle or end segment, we'll be doing different stuff. */ 
    if (closed) {
      if (pts[i].type == BEZ_LINE_TO) {
        line_bbox(&vsc,&vx,&full_lextra,&rt);
      } else {
        bicubicbezier2D_bbox(&vsc,
                             &pts[i].p1,&pts[i].p2,&pts[i].p3,
                             &bextra,
                             &rt);
      }    
    } else if (start) {
      if (pts[i].type == BEZ_LINE_TO) {
        if (end) {
          line_bbox(&vsc,&vx,&full_lextra,&rt);
        } else {
          line_bbox(&vsc,&vx,&start_lextra,&rt);
        }
      } else { /* BEZ_MOVE_TO */ 
        if (end) {
          bicubicbezier2D_bbox(&vsc,
                               &pts[i].p1,&pts[i].p2,&pts[i].p3,
                               extra,
                               &rt);
        } else {
          bicubicbezier2D_bbox(&vsc,
                               &pts[i].p1,&pts[i].p2,&pts[i].p3,
                               &start_bextra,
                               &rt);
        }
      }
    } else if (end) { /* end but not start. Not closed anyway. */
      if (pts[i].type == BEZ_LINE_TO) {
        line_bbox(&vsc,&vx,&end_lextra,&rt);
      } else {
        bicubicbezier2D_bbox(&vsc,
                             &pts[i].p1,&pts[i].p2,&pts[i].p3,
                             &end_bextra,
                             &rt);
      } 
    } else { /* normal case : middle segment (not closed shape). */
      if (pts[i].type == BEZ_LINE_TO) {
        line_bbox(&vsc,&vx,&lextra,&rt);
      } else {
        bicubicbezier2D_bbox(&vsc,
                             &pts[i].p1,&pts[i].p2,&pts[i].p3,
                             &bextra,
                             &rt);
      } 
    }   
    rectangle_union(rect,&rt);

    /* The following code enlarges a little the bounding box (if necessary) to 
       account with the "pointy corners" X (and PS) add when LINEJOIN_MITER mode is 
       in force. */

    if ((!start) && (!end)) { /* We have a non-extremity vertex. */
      Point vpx,vxn;
      real co,alpha;

      point_copy_add_scaled(&vpx,&vx,&vp,-1);
      point_normalize(&vpx);
      point_copy_add_scaled(&vxn,&vn,&vx,-1);
      point_normalize(&vxn);

      co = point_dot(&vpx,&vxn);      
      alpha = acos(-co); 
      if (co > -0.9816) { /* 0.9816 = cos(11deg) */
        /* we have a pointy join. */
        real overshoot;
        Point vovs,pto;

	if (finite(alpha))
	  overshoot = extra->middle_trans / sin(alpha/2.0);
	else /* prependicular? */
	  overshoot = extra->middle_trans;

        point_copy_add_scaled(&vovs,&vpx,&vxn,-1);
        point_normalize(&vovs);
        point_copy_add_scaled(&pto,&vx,&vovs,overshoot);
        
        rectangle_add_point(rect,&pto);
      } else {
        /* we don't have a pointy join. */
        Point vpxt,vxnt,tmp;

        point_get_perp(&vpxt,&vpx);
        point_get_perp(&vxnt,&vxn);
        
        point_copy_add_scaled(&tmp,&vx,&vpxt,1);
        rectangle_add_point(rect,&tmp);
        point_copy_add_scaled(&tmp,&vx,&vpxt,-1);
        rectangle_add_point(rect,&tmp);
        point_copy_add_scaled(&tmp,&vx,&vxnt,1);
        rectangle_add_point(rect,&tmp);
        point_copy_add_scaled(&tmp,&vx,&vxnt,-1);
        rectangle_add_point(rect,&tmp);
      }
    }
  }
}
Beispiel #16
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];
}