Beispiel #1
0
/*!
 * \brief Limit movability of control handles
 *
 * Update a corner to have less freedom in its control handles, arranging
 * the control points at some reasonable places.
 * @param bezier A bezierconn to straighten a corner of
 * @param comp_nr The index into the corner_types array of the corner to
 *                straighten.
 * \memberof _BezierConn
 */
static void
bezierconn_straighten_corner (BezierConn *bezier, int comp_nr)
{
  int next_nr = comp_nr+1;
  /* Neat thing would be to have the kind of straigthening depend on
     which handle was chosen:  Mid-handle does average, other leaves that
     handle where it is. */
  switch (bezier->bezier.corner_types[comp_nr]) {
  case BEZ_CORNER_SYMMETRIC: {
    Point pt1, pt2;

    pt1 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt1, &bezier->bezier.points[comp_nr].p2);
    pt2 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt2, &bezier->bezier.points[next_nr].p1);
    point_scale(&pt2, -1.0);
    point_add(&pt1, &pt2);
    point_scale(&pt1, 0.5);
    pt2 = pt1;
    point_scale(&pt1, -1.0);
    point_add(&pt1, &bezier->bezier.points[comp_nr].p3);
    point_add(&pt2, &bezier->bezier.points[comp_nr].p3);
    bezier->bezier.points[comp_nr].p2 = pt1;
    bezier->bezier.points[next_nr].p1 = pt2;
    bezierconn_update_data(bezier);
  }
  break;
  case BEZ_CORNER_SMOOTH: {
    Point pt1, pt2;
    real len1, len2;
    pt1 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt1, &bezier->bezier.points[comp_nr].p2);
    pt2 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt2, &bezier->bezier.points[next_nr].p1);
    len1 = point_len(&pt1);
    len2 = point_len(&pt2);
    point_scale(&pt2, -1.0);
    if (len1 > 0)
      point_normalize(&pt1);
    if (len2 > 0)
      point_normalize(&pt2);
    point_add(&pt1, &pt2);
    point_scale(&pt1, 0.5);
    pt2 = pt1;
    point_scale(&pt1, -len1);
    point_add(&pt1, &bezier->bezier.points[comp_nr].p3);
    point_scale(&pt2, len2);
    point_add(&pt2, &bezier->bezier.points[comp_nr].p3);
    bezier->bezier.points[comp_nr].p2 = pt1;
    bezier->bezier.points[next_nr].p1 = pt2;
    bezierconn_update_data(bezier);
  }
    break;
  case BEZ_CORNER_CUSP:
    break;
  }
}
Beispiel #2
0
/* copied from lib/diarenderer.c, the one there should be removed */
static gboolean
is_right_hand (const Point *a, const Point *b, const Point *c)
{
    Point dot1, dot2;

    dot1 = *a;
    point_sub(&dot1, c);
    point_normalize(&dot1);
    dot2 = *b;
    point_sub(&dot2, c);
    point_normalize(&dot2);
    return point_cross(&dot1, &dot2) > 0;
}
Beispiel #3
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 #4
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 #5
0
/*!
 * \brief Rotate path towards clicked point
 *
 * Rotate the given path around it's center with the angle given by
 * the top center handle and the clicked point. This function is
 * available with the context menu of the 'Standard - Path' object.
 * @return Undo information
 *
 * \relates _StdPath
 */
static ObjectChange *
_path_rotate_callback (DiaObject *obj, Point *clicked, gpointer data)
{
  StdPath *sp = (StdPath *)obj;
  real cx = (sp->object.bounding_box.left + sp->object.bounding_box.right) / 2;
  real cy = (sp->object.bounding_box.top + sp->object.bounding_box.bottom) / 2;
  DiaMatrix m = {1, 0, 0, 1, 0, 0 };
  DiaMatrix translate = {1, 0, 0, 1, 0, 0 };
  Point d;

  d.x = clicked->x - cx;
  d.y = clicked->y - cy;
  point_normalize (&d);
  /* to make the top, center handle clicked no rotation we subtract -PI/2 */
  dia_matrix_set_angle_and_scales (&m, atan2 (d.y, d.x) + M_PI/2.0, 1.0, 1.0);

  /* rotate around center */
  translate.x0 = cx;
  translate.y0 = cy;
  dia_matrix_multiply (&m, &m, &translate);
  translate.x0 = -cx;
  translate.y0 = -cy;
  dia_matrix_multiply (&m, &translate, &m);

  _path_transform (sp, &m);
  return _path_object_transform_change_create (obj, &m);
}
Beispiel #6
0
/*!
 * \brief Move one of the objects handles
 * \memberof Outline
 */
static ObjectChange*
outline_move_handle (Outline *outline,
                     Handle *handle,
		     Point *to, ConnectionPoint *cp,
		     HandleMoveReason reason, ModifierKeys modifiers)
{
  DiaObject *obj = &outline->object;
  Point start = obj->position;
  Point end = outline->ink_rect[2];
  real dist, old_dist = distance_point_point (&start, &end);
  Point norm = end;
  point_sub (&norm, &start);
  point_normalize (&norm);
  /* we use this to modify angle and scale */
  switch (handle->id) {
  case HANDLE_RESIZE_NW :
    start = *to;
    break;
  case HANDLE_RESIZE_SE :
    end = *to;
    break;
  default :
    g_warning ("Outline unknown handle");
  }
  dist = distance_point_point (&start, &end);
  /* disallow everything below a certain level, otherwise the font-size could become invalid */
  if (dist > 0.1) {
    obj->position = start;

    outline->font_height *= (dist / old_dist);

    outline_update_data (outline);
  }
  return NULL;
}
static void
implements_move_handle(Implements *implements, Handle *handle,
		 Point *to, HandleMoveReason reason, ModifierKeys modifiers)
{
  Point v1, v2;
  
  assert(implements!=NULL);
  assert(handle!=NULL);
  assert(to!=NULL);

  if (handle->id == HANDLE_MOVE_TEXT) {
    implements->text_pos = *to;
  } else if (handle->id == HANDLE_CIRCLE_SIZE) {
    v1 = implements->connection.endpoints[0];
    point_sub(&v1, &implements->connection.endpoints[1]);
    point_normalize(&v1);
    v2 = *to;
    point_sub(&v2, &implements->connection.endpoints[1]);
    implements->circle_diameter = point_dot(&v1, &v2);
    if (implements->circle_diameter<0.03)
      implements->circle_diameter = 0.03;
  } else {
    v1 = implements->connection.endpoints[1];
    connection_move_handle(&implements->connection, handle->id, to, reason);
    point_sub(&v1, &implements->connection.endpoints[1]);
    point_sub(&implements->text_pos, &v1);
  }

  implements_update_data(implements);
}
Beispiel #8
0
/* finds the point intersecting the full circle
 * on the vector defined by the center and Point *to
 * that point is returned in Point *best if 1 is returned */
static int
arc_find_radial(const Arc *arc, const Point *to, Point *best)
{
    Point tmp;
    tmp = *to;
    point_sub(&tmp, &arc->center);
    point_normalize(&tmp);
    point_scale(&tmp,arc->radius);
    point_add(&tmp, &arc->center);
    *best = tmp;
    return 1;

}
Beispiel #9
0
void
polyline_calculate_gap_endpoints(Polyline *polyline, Point *gap_endpoints)
{
  Point  start_vec, end_vec;
  ConnectionPoint *start_cp, *end_cp;
  int n = polyline->poly.numpoints;

  gap_endpoints[0] = polyline->poly.points[0];
  gap_endpoints[1] = polyline->poly.points[n-1];

  start_cp = (polyline->poly.object.handles[0])->connected_to;
  end_cp = (polyline->poly.object.handles[polyline->poly.object.num_handles-1])->connected_to;

  if (connpoint_is_autogap(start_cp)) {
      gap_endpoints[0] = calculate_object_edge(&gap_endpoints[0],
					   &polyline->poly.points[1],
					   start_cp->object);
  }
  if (connpoint_is_autogap(end_cp)) {    
      gap_endpoints[1] = calculate_object_edge(&gap_endpoints[1],
					   &polyline->poly.points[n-2],
					   end_cp->object);
  }

  start_vec = gap_endpoints[0];
  point_sub(&start_vec, &polyline->poly.points[0]);
  point_normalize(&start_vec);

  end_vec = gap_endpoints[1];
  point_sub(&end_vec, &polyline->poly.points[n-1]);
  point_normalize(&end_vec);
  
  /* add absolute gap */
  point_add_scaled(&gap_endpoints[0], &start_vec, polyline->absolute_start_gap);
  point_add_scaled(&gap_endpoints[1], &end_vec, polyline->absolute_end_gap);
}
Beispiel #10
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 #11
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 #12
0
void 
connpointline_putonaline(ConnPointLine *cpl,Point *start,Point *end, gint dirs)
{
  Point se_vector;
  real se_len,pseudopoints;
  int i;
  GSList *elem;

  point_copy(&se_vector, end);
  point_sub(&se_vector, start);
  
  se_len = point_len(&se_vector);
  
  if (se_len > 0)
    point_normalize(&se_vector);
  
  cpl->start = *start;
  cpl->end = *end;
  
  if (dirs != DIR_NONE)
    /* use the oone givne by the caller */;
  else if (fabs(se_vector.x) > fabs(se_vector.y))
    dirs = DIR_NORTH|DIR_SOUTH;
  else
    dirs = DIR_EAST|DIR_WEST;

  pseudopoints = cpl->num_connections + 1; /* here, we count the start and end 
					    points as eating real positions. */
  for (i=0, elem=cpl->connections; 
       i<cpl->num_connections; 
       i++,elem=g_slist_next(elem)) {
    ConnectionPoint *cp = (ConnectionPoint *)(elem->data);
    cp->pos = se_vector;
    cp->directions = dirs;
    point_scale(&cp->pos,se_len * (i+1.0)/pseudopoints);
    point_add(&cp->pos,start);
  }
}
Beispiel #13
0
/*!
 * \brief Set the other point of the pattern
 *
 * The meaning of the point depends on the type of the pattern.
 * For line gradient it is the second point giving the direction.
 * With a radial gradient it is the focal point.
 *
 * \ingroup DiaPattern
 */
void
dia_pattern_set_point (DiaPattern *self, real x, real y)
{
  self->other.x = x;
  self->other.y = y;
  /* with radial we have to ensure the point is in circle */
  if (self->type == DIA_RADIAL_GRADIENT) {
    real dist = distance_ellipse_point (&self->start, self->radius*2, self->radius*2, 0.0, &self->other);
    if (dist > 0) {
      /* If the point defined by ‘fx’ and ‘fy’ lies outside the circle defined
       * by ‘cx’, ‘cy’ and ‘r’, then the user agent shall set the focal point to
       * the intersection of the line from (‘cx’, ‘cy’) to (‘fx’, ‘fy’) with the
       * circle defined by ‘cx’, ‘cy’ and ‘r’
       */
      Point p1 = self->start;
      Point p2 = self->other;
      point_sub (&p2, &p1);
      point_normalize (&p2);
      point_add_scaled (&p1, &p2, self->radius);
      self->other = p1;
    }
  }
}
Beispiel #14
0
ObjectChange *
beziershape_move_handle(BezierShape *bezier, Handle *handle,
			Point *to, ConnectionPoint *cp,
			HandleMoveReason reason, ModifierKeys modifiers)
{
  int handle_nr, comp_nr, next_nr, prev_nr;
  Point delta, pt;
  
  delta = *to;
  point_sub(&delta, &handle->pos);

  handle_nr = get_handle_nr(bezier, handle);
  comp_nr = get_comp_nr(handle_nr);
  next_nr = comp_nr + 1;
  prev_nr = comp_nr - 1;
  if (comp_nr == bezier->numpoints - 1)
    next_nr = 1;
  if (comp_nr == 1)
    prev_nr = bezier->numpoints - 1;
  
  switch(handle->id) {
  case HANDLE_BEZMAJOR:
    if (comp_nr == bezier->numpoints - 1) {
      bezier->points[comp_nr].p3 = *to;
      bezier->points[0].p1 = bezier->points[0].p3 = *to;
      point_add(&bezier->points[comp_nr].p2, &delta);
      point_add(&bezier->points[1].p1, &delta);
    } else {
      bezier->points[comp_nr].p3 = *to;
      point_add(&bezier->points[comp_nr].p2, &delta);
      point_add(&bezier->points[comp_nr+1].p1, &delta);
    }
    break;
  case HANDLE_LEFTCTRL:
    bezier->points[comp_nr].p2 = *to;
    switch (bezier->corner_types[comp_nr]) {
    case BEZ_CORNER_SYMMETRIC:
      pt = bezier->points[comp_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p2);
      point_add(&pt, &bezier->points[comp_nr].p3);
      bezier->points[next_nr].p1 = pt;
      break;
    case BEZ_CORNER_SMOOTH: {
      real len;

      pt = bezier->points[next_nr].p1;
      point_sub(&pt, &bezier->points[comp_nr].p3);
      len = point_len(&pt);

      pt = bezier->points[comp_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p2);
      if (point_len(&pt) > 0)
	point_normalize(&pt);
      else {
	pt.x = 1.0; pt.y = 0.0;
      }
      point_scale(&pt, len);
      point_add(&pt, &bezier->points[comp_nr].p3);
      bezier->points[next_nr].p1 = pt;
      break;
    }
    case BEZ_CORNER_CUSP:
      /* no mirror point movement required */
      break;
    }
    break;
  case HANDLE_RIGHTCTRL:
    bezier->points[comp_nr].p1 = *to;
    switch (bezier->corner_types[prev_nr]) {
    case BEZ_CORNER_SYMMETRIC:
      pt = bezier->points[prev_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p1);
      point_add(&pt, &bezier->points[prev_nr].p3);
      bezier->points[prev_nr].p2 = pt;
      break;
    case BEZ_CORNER_SMOOTH: {
      real len;

      pt = bezier->points[prev_nr].p2;
      point_sub(&pt, &bezier->points[prev_nr].p3);
      len = point_len(&pt);

      pt = bezier->points[prev_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p1);
      if (point_len(&pt) > 0)
	point_normalize(&pt);
      else {
	pt.x = 1.0; pt.y = 0.0;
      }
      point_scale(&pt, len);
      point_add(&pt, &bezier->points[prev_nr].p3);
      bezier->points[prev_nr].p2 = pt;
      break;
    }
    case BEZ_CORNER_CUSP:
      /* no mirror point movement required */
      break;
    }
    break;
  default:
    message_error("Internal error in beziershape_move_handle.");
    break;
  }
  return NULL;
}
Beispiel #15
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 #16
0
static ObjectChange*
bus_move_handle(Bus *bus, Handle *handle,
		Point *to, ConnectionPoint *cp,
		HandleMoveReason reason, ModifierKeys modifiers)
{
  Connection *conn = &bus->connection;
  Point *endpoints;
  static real *parallel=NULL;
  static real *perp=NULL;
  static int max_num=0;
  Point vhat, vhatperp;
  Point u;
  real vlen, vlen2;
  real len_scale;
  int i;

  if (bus->num_handles>max_num) {
    if (parallel!=NULL) {
      g_free(parallel);
      g_free(perp);
    }
    parallel = g_malloc(sizeof(real)*bus->num_handles);
    perp = g_malloc(sizeof(real)*bus->num_handles);
    max_num = bus->num_handles;
  }

  if (handle->id == HANDLE_BUS) {
    handle->pos = *to;
  } else {
    endpoints = &conn->endpoints[0];
    vhat = endpoints[1];
    point_sub(&vhat, &endpoints[0]);
    if ((fabs(vhat.x) == 0.0) && (fabs(vhat.y)==0.0)) {
      vhat.x += 0.01;
    }
    vlen = sqrt(point_dot(&vhat, &vhat));
    point_scale(&vhat, 1.0/vlen);
    
    vhatperp.x = -vhat.y;
    vhatperp.y =  vhat.x;
    for (i=0;i<bus->num_handles;i++) {
      u = bus->handles[i]->pos;
      point_sub(&u, &endpoints[0]);
      parallel[i] = point_dot(&vhat, &u);
      perp[i] = point_dot(&vhatperp, &u);
    }
    
    connection_move_handle(&bus->connection, handle->id, to, cp, 
			   reason, modifiers);

    vhat = endpoints[1];
    point_sub(&vhat, &endpoints[0]);
    if ((fabs(vhat.x) == 0.0) && (fabs(vhat.y)==0.0)) {
      vhat.x += 0.01;
    }
    vlen2 = sqrt(point_dot(&vhat, &vhat));
    len_scale = vlen2 / vlen;
    point_normalize(&vhat);
    vhatperp.x = -vhat.y;
    vhatperp.y =  vhat.x;
    for (i=0;i<bus->num_handles;i++) {
      if (bus->handles[i]->connected_to == NULL) {
	u = vhat;
	point_scale(&u, parallel[i]*len_scale);
	point_add(&u, &endpoints[0]);
	bus->parallel_points[i] = u;
	u = vhatperp;
	point_scale(&u, perp[i]);
	point_add(&u, &bus->parallel_points[i]);
	bus->handles[i]->pos = u;
	}
    }
  }

  bus_update_data(bus);

  return NULL;
}
Beispiel #17
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 #18
0
static void
wanlink_update_data(WanLink *wanlink)
{
  Connection *conn = &wanlink->connection;
  DiaObject *obj = (DiaObject *) wanlink;
  Point v, vhat;
  Point *endpoints;
  real width, width_2;
  real len, angle;
  Point origin;
  int i;
  Matrix m;
  

  width = wanlink->width;
  width_2 = width / 2.0;
  
  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);

  connection_update_boundingbox(conn);

  /** compute the polygon **/
  origin = wanlink->connection.endpoints [0];
  len = point_len (&v);

  angle = atan2 (vhat.y, vhat.x) - M_PI_2;

    /* The case of the wanlink */
  wanlink->poly[0].x = (width * 0.50) - width_2;
  wanlink->poly[0].y = (len * 0.00);
  wanlink->poly[1].x = (width * 0.50) - width_2;
  wanlink->poly[1].y = (len * 0.45);
  wanlink->poly[2].x = (width * 0.94) - width_2;
  wanlink->poly[2].y = (len * 0.45);
  wanlink->poly[3].x = (width * 0.50) - width_2;
  wanlink->poly[3].y = (len * 1.00);
  wanlink->poly[4].x = (width * 0.50) - width_2;
  wanlink->poly[4].y = (len * 0.55);
  wanlink->poly[5].x = (width * 0.06) - width_2;
  wanlink->poly[5].y = (len * 0.55);
  
  /* rotate */
  _identity_matrix (m);
  _rotate_matrix (m, angle);

  obj->bounding_box.top = origin.y;
  obj->bounding_box.left = origin.x;
  obj->bounding_box.bottom = conn->endpoints[1].y;
  obj->bounding_box.right = conn->endpoints[1].x;
  for (i = 0; i <  WANLINK_POLY_LEN; i++) 
  {
      Point new_pt;
      
      _transform_point (m, &wanlink->poly[i], 
		        &new_pt);
      point_add (&new_pt, &origin);
      wanlink->poly[i] = new_pt;
  }
  /* calculate bounding box */
  {
    PolyBBExtras bbex = {0, 0, wanlink->width/2, 0, 0 };
    polyline_bbox (&wanlink->poly[0], WANLINK_POLY_LEN, &bbex, TRUE, &obj->bounding_box);
  }


  connection_update_handles(conn);
}
Beispiel #19
0
static ObjectChange*
flow_move_handle(Flow *flow, Handle *handle,
		 Point *to, ConnectionPoint *cp,
		 HandleMoveReason reason, ModifierKeys modifiers)
{
  Point p1, p2;
  Point *endpoints;
  
  assert(flow!=NULL);
  assert(handle!=NULL);
  assert(to!=NULL);

  if (handle->id == HANDLE_MOVE_TEXT) {
    flow->textpos = *to;
  } else  {
    real dest_length ;
    real orig_length2 ;
    real along_mag, norm_mag ;
    Point along ;

    endpoints = &flow->connection.endpoints[0]; 
    p1 = flow->textpos ;
    point_sub( &p1, &endpoints[0] ) ;

    p2 = endpoints[1] ;
    point_sub( &p2, &endpoints[0] ) ;
    orig_length2= point_dot( &p2, &p2 ) ;
    along = p2 ;
    if ( orig_length2 > 1e-5 ) {
      along_mag = point_dot( &p2, &p1 )/sqrt(orig_length2) ;
      along_mag *= along_mag ;
      norm_mag = point_dot( &p1, &p1 ) ;
      norm_mag = (real)sqrt( (double)( norm_mag - along_mag ) ) ;
      along_mag = (real)sqrt( along_mag/orig_length2 ) ;
      if ( p1.x*p2.y - p1.y*p2.x > 0.0 )
	norm_mag = -norm_mag ;
    } else {
      along_mag = 0.5 ;
      norm_mag = (real)sqrt( (double) point_dot( &p1, &p1 ) ) ;
    }

    connection_move_handle(&flow->connection, handle->id, to, cp, 
			   reason, modifiers);

    p2 = endpoints[1] ;
    point_sub( &p2, &endpoints[0] ) ;
    flow->textpos = endpoints[0] ;
    along = p2 ;
    p2.x = -along.y ;
    p2.y = along.x ;
    dest_length = point_dot( &p2, &p2 ) ;
    if ( dest_length > 1e-5 ) {
      point_normalize( &p2 ) ;
    } else {
      p2.x = 0.0 ; p2.y = -1.0 ; 
    }
    point_scale( &p2, norm_mag ) ;
    point_scale( &along, along_mag ) ;
    point_add( &flow->textpos, &p2 ) ;
    point_add( &flow->textpos, &along ) ;
  }

  flow_update_data(flow);

  return NULL;
}
Beispiel #20
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 #21
0
/*!
 * \brief Move one of the handles associated with the
 * @param bezier The object whose handle is being moved.
 * @param handle The handle being moved.
 * @param to The position it has been moved to (corrected for
 *   vertical/horizontal only movement).
 * @param cp If non-NULL, the connectionpoint found at this position.
 *   If @a cp is NULL, there may or may not be a connectionpoint.
 * @param reason ignored
 * @param modifiers ignored
 * @return NULL
 * \memberof BezierConn
 */
ObjectChange*
bezierconn_move_handle (BezierConn *bezier,
			Handle *handle,
			Point *to,
			ConnectionPoint *cp,
			HandleMoveReason reason,
			ModifierKeys modifiers)
{
  int handle_nr, comp_nr;
  Point delta, pt;
  
  delta = *to;
  point_sub(&delta, &handle->pos);

  handle_nr = get_handle_nr(bezier, handle);
  comp_nr = get_comp_nr(handle_nr);
  switch(handle->id) {
  case HANDLE_MOVE_STARTPOINT:
    bezier->bezier.points[0].p1 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[1].p1, &delta);
    break;
  case HANDLE_MOVE_ENDPOINT:
    bezier->bezier.points[bezier->bezier.num_points-1].p3 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[bezier->bezier.num_points-1].p2, &delta);
    break;
  case HANDLE_BEZMAJOR:
    bezier->bezier.points[comp_nr].p3 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[comp_nr].p2, &delta);
    point_add(&bezier->bezier.points[comp_nr+1].p1, &delta);
    break;
  case HANDLE_LEFTCTRL:
    bezier->bezier.points[comp_nr].p2 = *to;
    if (comp_nr < bezier->bezier.num_points - 1) {
      switch (bezier->bezier.corner_types[comp_nr]) {
      case BEZ_CORNER_SYMMETRIC:
	pt = bezier->bezier.points[comp_nr].p3;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p2);
	point_add(&pt, &bezier->bezier.points[comp_nr].p3);
	bezier->bezier.points[comp_nr+1].p1 = pt;
	break;
      case BEZ_CORNER_SMOOTH: {
	real len;
	pt = bezier->bezier.points[comp_nr+1].p1;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p3);
	len = point_len(&pt);
	pt = bezier->bezier.points[comp_nr].p2;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p3);
	if (point_len(&pt) > 0)
	  point_normalize(&pt);
	else { pt.x = 1.0; pt.y = 0.0; }
	point_scale(&pt, -len);
	point_add(&pt, &bezier->bezier.points[comp_nr].p3);
	bezier->bezier.points[comp_nr+1].p1 = pt;
	break;
      }	
      case BEZ_CORNER_CUSP:
	/* Do nothing to the other guy */
	break;
      }
    }
    break;
  case HANDLE_RIGHTCTRL:
    bezier->bezier.points[comp_nr].p1 = *to;
    if (comp_nr > 1) {
      switch (bezier->bezier.corner_types[comp_nr-1]) {
      case BEZ_CORNER_SYMMETRIC:
	pt = bezier->bezier.points[comp_nr - 1].p3;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p1);
	point_add(&pt, &bezier->bezier.points[comp_nr - 1].p3);
	bezier->bezier.points[comp_nr-1].p2 = pt;
	break;
      case BEZ_CORNER_SMOOTH: {
	real len;
	pt = bezier->bezier.points[comp_nr-1].p2;
	point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3);
	len = point_len(&pt);
	pt = bezier->bezier.points[comp_nr].p1;
	point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3);
	if (point_len(&pt) > 0)
	  point_normalize(&pt);
	else { pt.x = 1.0; pt.y = 0.0; }
	point_scale(&pt, -len);
	point_add(&pt, &bezier->bezier.points[comp_nr-1].p3);
	bezier->bezier.points[comp_nr-1].p2 = pt;
	break;
      }	
      case BEZ_CORNER_CUSP:
	/* Do nothing to the other guy */
	break;
      }
    }
    break;
  default:
    g_warning("Internal error in bezierconn_move_handle.\n");
    break;
  }
  return NULL;
}
Beispiel #22
0
/*
 * Draw the module into the image using the given view transformation matrix [VTM], 
 * Lighting and DrawState by traversing the list of Elements. 
 * (For now, Lighting can be an empty structure.)
 */
void module_draw(Module *md, Matrix *VTM, Matrix *GTM, DrawState *ds, 
				Lighting *lighting, Image *src){
				
	/* for antialiasing
	Module *thickLineMod = module_create();			
	Element *thickLineE;
	float dx, dy, dz, lineLength;
	Vector u, v, w;*/
	
	// all locally needed variables
	Matrix LTM, tempGTM;
	Line tempLine;
	DrawState *tempds = drawstate_create();
	Point tempPointLTM, tempPointGTM, tempPointVTM;
	Polyline *tempPolyline = polyline_create();
	Polygon *tempPolygon = polygon_create();
	Element *e = md->head;
	
	matrix_identity(&LTM);
	
	// loop until the end of the linked list is reached
	while(e){
		//printf("Handling type %d\n", e->type);
		// draw based on type
		switch(e->type){
			case ObjNone:
				break;
			case ObjPoint:
				//printf("drawing point ");
				// copy, xform, normalize, draw
				matrix_xformPoint(&LTM, &(e->obj.point), &tempPointLTM);
				matrix_xformPoint(GTM, &tempPointLTM, &tempPointGTM);
				matrix_xformPoint(VTM, &tempPointGTM, &tempPointVTM);
				point_normalize(&(tempPointVTM));
				//point_print(&tempPointVTM, stdout);
				point_draw(&tempPointVTM, src, ds->color);
				break;
			case ObjLine:
				line_copy(&tempLine, &(e->obj.line));
				//printf("drawing line ");
				// copy, xform, normalize, draw
				matrix_xformLine(&LTM, &tempLine);
				matrix_xformLine(GTM, &tempLine);
				matrix_xformLine(VTM, &tempLine);
				line_normalize(&tempLine);
				line_draw(&tempLine, src, ds->color);
				//line_print(&tempLine, stdout);
				/*if(antialias){
					dx = tempLine.b.val[0]-tempLine.a.val[0];
					dy = tempLine.b.val[1]-tempLine.a.val[1];
					dz = tempLine.b.val[2]-tempLine.a.val[2];
					lineLength = sqrt(dx*dx+dy*dy+dz*dz);
					module_scale( thickLineMod, 1, lineLength, 1 );
					vector_set(&v, dx, dy, dz);
					vector_normalize(&v);
					vector_set(&u, -dz, dx, dy);
					vector_cross(&u, &v, &w);
					vector_cross(&v, &w, &u);
					vector_normalize(&u);
					vector_normalize(&w);
					module_rotateXYZ( thickLineMod, &u, &v, &w );
					module_translate( thickLineMod,	tempLine.a.val[0], 
													tempLine.a.val[1], 
													tempLine.a.val[2] );
					module_cylinder( thickLineMod, 4, 1, 1, 0, 0, 0 );
					thickLineE = element_init(ObjModule, thickLineMod);
					thickLineE->next = e->next;
					e->next = thickLineE;
				}*/
				break;
			case ObjPolyline:
				//printf("drawing polyline ");
				// copy, xform, normalize, draw
				polyline_copy(tempPolyline, &(e->obj.polyline));
				matrix_xformPolyline(&LTM, tempPolyline);
				matrix_xformPolyline(GTM, tempPolyline);
				matrix_xformPolyline(VTM, tempPolyline);
				polyline_normalize(tempPolyline);
				//polyline_print(tempPolyline, stdout);
				polyline_draw(tempPolyline, src, ds->color);
				break;
			case ObjPolygon:
				//printf("drawing polygon ");
				// copy, xform, normalize, draw
				polygon_copy(tempPolygon, &(e->obj.polygon));
				matrix_xformPolygon(&LTM, tempPolygon);
				matrix_xformPolygon(GTM, tempPolygon);
				matrix_xformPolygon(VTM, tempPolygon);
				polygon_normalize(tempPolygon);
				//polygon_print(tempPolygon, stdout);
				polygon_draw(tempPolygon, src, ds);
				break;
			case ObjColor:
				drawstate_setColor(ds, e->obj.color);
				break;
			case ObjBodyColor:
				break;
			case ObjSurfaceColor:
				break;
			case ObjSurfaceCoeff:
				break;
			case ObjLight:
				break;
			case ObjIdentity:
				matrix_identity(&LTM);
				break;
			case ObjMatrix:
				matrix_multiply(&(e->obj.matrix), &LTM, &LTM);
				break;
			case ObjModule:
				matrix_multiply(GTM, &LTM, &tempGTM);
				drawstate_copy(tempds, ds);
				module_draw(e->obj.module, VTM, &tempGTM, tempds, lighting, src);
				break;
			default:
				printf("ObjectType %d is not handled in module_draw\n",e->type);
		}
		
		// advance traversal
		e = e->next;
	}
	
	// clean up
	polygon_free(tempPolygon);
	polyline_free(tempPolyline);
	free(tempds);
}
Beispiel #23
0
static void
compute_gap_points(Bezierline *bezierline, Point *gap_points)
{
        real bez_length;
        BezierConn *bez = &bezierline->bez;
        Point vec_start, vec_end;


        gap_points[0] = bez->bezier.points[0].p1;
        gap_points[1] = bez->bezier.points[1].p1;
        gap_points[2] = bez->bezier.points[bez->bezier.num_points-1].p2;
        gap_points[3] = bez->bezier.points[bez->bezier.num_points-1].p3;

        point_copy(&vec_start, &gap_points[1]);
        point_sub(&vec_start, &gap_points[0]);
        point_normalize(&vec_start); /* unit vector pointing from first point */
        point_copy(&vec_end, &gap_points[2]);
        point_sub(&vec_end, &gap_points[3]);
        point_normalize(&vec_end); /* unit vector pointing from last point */


        bez_length = approx_bez_length(bez) ;

        if (connpoint_is_autogap(bez->object.handles[0]->connected_to) &&
               (bez->object.handles[0])->connected_to != NULL &&
               (bez->object.handles[0])->connected_to->object != NULL ) {
            Point end;
            point_copy(&end, &gap_points[0]);
            point_add_scaled(&end, &vec_start, bez_length); /* far away on the same slope */
            end = calculate_object_edge(&gap_points[0], &end,
                            (bez->object.handles[0])->connected_to->object);
            point_sub(&end, &gap_points[0]); /* vector from old start to new start */
            /* move points */
            point_add(&gap_points[0], &end);
            point_add(&gap_points[1], &end);
        }

        if (connpoint_is_autogap(bez->object.handles[3*(bez->bezier.num_points-1)]->connected_to) &&
                (bez->object.handles[3*(bez->bezier.num_points-1)])->connected_to != NULL &&
                (bez->object.handles[3*(bez->bezier.num_points-1)])->connected_to->object != NULL) {
            Point end;
            point_copy(&end, &gap_points[3]);
            point_add_scaled(&end, &vec_end, bez_length); /* far away on the same slope */
            end = calculate_object_edge(&gap_points[3], &end,
                            (bez->object.handles[3*(bez->bezier.num_points-1)])->connected_to->object);
            point_sub(&end, &gap_points[3]); /* vector from old end to new end */
            /* move points */
            point_add(&gap_points[3], &end);
            point_add(&gap_points[2], &end);
        }


        /* adds the absolute start gap  according to the slope at the first point */
        point_add_scaled(&gap_points[0], &vec_start, bezierline->absolute_start_gap);
        point_add_scaled(&gap_points[1], &vec_start, bezierline->absolute_start_gap);

        /* adds the absolute end gap  according to the slope at the last point */
        point_add_scaled(&gap_points[2], &vec_end, bezierline->absolute_end_gap);
        point_add_scaled(&gap_points[3], &vec_end, bezierline->absolute_end_gap);


}
Beispiel #24
0
static DiaObject *
flow_create(Point *startpoint,
	    void *user_data,
	    Handle **handle1,
	    Handle **handle2)
{
  Flow *flow;
  Connection *conn;
  DiaObject *obj;
  LineBBExtras *extra;
  Point p ;
  Point n ;
  DiaFont *font;

  flow = g_malloc0(sizeof(Flow));

  conn = &flow->connection;
  conn->endpoints[0] = *startpoint;
  conn->endpoints[1] = *startpoint;
  conn->endpoints[1].x += 1.5;
 
  obj = &conn->object;
  extra = &conn->extra_spacing;

  obj->type = &flow_type;
  obj->ops = &flow_ops;
  
  connection_init(conn, 3, 0);

  p = conn->endpoints[1] ;
  point_sub( &p, &conn->endpoints[0] ) ;
  point_scale( &p, 0.5 ) ;
  n.x = p.y ;
  n.y = -p.x ;
  if ( fabs(n.x) < 1.e-5 && fabs(n.y) < 1.e-5 ) {
    n.x = 0. ;
    n.y = -1. ;
  } else {
    point_normalize( &n ) ;
  }
  point_scale( &n, 0.5*FLOW_FONTHEIGHT ) ;

  point_add( &p, &n ) ;
  point_add( &p, &conn->endpoints[0] ) ;
  flow->textpos = p;

  font = dia_font_new_from_style(DIA_FONT_SANS, FLOW_FONTHEIGHT);

  flow->text = new_text("", font, FLOW_FONTHEIGHT, &p, &color_black, ALIGN_CENTER);
  dia_font_unref(font);  

  flow->text_handle.id = HANDLE_MOVE_TEXT;
  flow->text_handle.type = HANDLE_MINOR_CONTROL;
  flow->text_handle.connect_type = HANDLE_NONCONNECTABLE;
  flow->text_handle.connected_to = NULL;
  flow->text_handle.pos = p;
  obj->handles[2] = &flow->text_handle;

  extra->start_long = 
    extra->end_long =
    extra->start_trans = FLOW_WIDTH/2.0;
  extra->end_trans = MAX(FLOW_WIDTH, FLOW_ARROWLEN) / 2.0;
  flow_update_data(flow);
  *handle1 = obj->handles[0];
  *handle2 = obj->handles[1];
  
  return &flow->connection.object;
}
Beispiel #25
0
Datei: bus.c Projekt: GNOME/dia
static ObjectChange*
bus_move_handle(Bus *bus, Handle *handle,
		Point *to, ConnectionPoint *cp,
		HandleMoveReason reason, ModifierKeys modifiers)
{
  Connection *conn = &bus->connection;
  Point *endpoints;
  real *parallel=NULL;
  real *perp=NULL;
  Point vhat, vhatperp;
  Point u;
  real vlen, vlen2;
  real len_scale;
  int i;
  const int num_handles = bus->num_handles; /* const to help scan-build */

  /* code copied to Misc/tree.c */
  parallel = (real *)g_alloca (num_handles * sizeof(real));
  perp = (real *)g_alloca (num_handles * sizeof(real));

  if (handle->id == HANDLE_BUS) {
    handle->pos = *to;
  } else {
    endpoints = &conn->endpoints[0];
    vhat = endpoints[1];
    point_sub(&vhat, &endpoints[0]);
    if ((fabs(vhat.x) == 0.0) && (fabs(vhat.y)==0.0)) {
      vhat.x += 0.01;
    }
    vlen = sqrt(point_dot(&vhat, &vhat));
    point_scale(&vhat, 1.0/vlen);

    vhatperp.x = -vhat.y;
    vhatperp.y =  vhat.x;
    for (i=0;i<num_handles;i++) {
      u = bus->handles[i]->pos;
      point_sub(&u, &endpoints[0]);
      parallel[i] = point_dot(&vhat, &u);
      perp[i] = point_dot(&vhatperp, &u);
    }

    connection_move_handle(&bus->connection, handle->id, to, cp,
			   reason, modifiers);

    vhat = endpoints[1];
    point_sub(&vhat, &endpoints[0]);
    if ((fabs(vhat.x) == 0.0) && (fabs(vhat.y)==0.0)) {
      vhat.x += 0.01;
    }
    vlen2 = sqrt(point_dot(&vhat, &vhat));
    len_scale = vlen2 / vlen;
    point_normalize(&vhat);
    vhatperp.x = -vhat.y;
    vhatperp.y =  vhat.x;
    for (i=0;i<num_handles;i++) {
      if (bus->handles[i]->connected_to == NULL) {
	u = vhat;
	point_scale(&u, parallel[i]*len_scale);
	point_add(&u, &endpoints[0]);
	bus->parallel_points[i] = u;
	u = vhatperp;
	point_scale(&u, perp[i]);
	point_add(&u, &bus->parallel_points[i]);
	bus->handles[i]->pos = u;
	}
    }
  }

  bus_update_data(bus);

  return NULL;
}